Bug #7464
opencrossbow allows to create a vnic with existing name
0%
Description
How to reproduce:
create an etherstub:
dladm create-etherstub hostswitch0
create a vnic for it:
dladm create-vnic -l sw0 vn2
now test that dladm does not allow to create another vnic with the same name:
service# dladm create-vnic -l sw0 vn2 dladm: vnic creation over sw0 failed: object already exists
assing the new vnic to a zone and boot it
service# cat /etc/zones/zhost02.xml <?xml version="1.0"?> <!DOCTYPE zone PUBLIC "-//Sun Microsystems Inc//DTD Zones//EN" "file:///usr/share/lib/xml/dtd/zonecfg.dtd.1"> <!-- DO NOT EDIT THIS FILE. Use zonecfg(1M) instead. --> <zone name="zhost02" zonepath="/zones/zhost02" autoboot="false" brand="ipkg" limitpriv="default" scheduling-class="FSS" ip-type="exclusive"> <network physical="vn2"/> <filesystem special="/hosting/zhost02" directory="/hosting" type="lofs"/> </zone> service# zoneadm -z zhost02 boot service# zoneadm list -iv ID NAME STATUS PATH BRAND IP 0 global running / ipkg shared 1 zhoster01 running /zones/zhoster01 ipkg excl 4 zhost02 running /zones/zhost02 ipkg excl
The zone is running, now let create anothe vnic with the same name:
service# dladm create-vnic -l sw0 vn2 service# echo $? 0
Wow! It is created successfully (why? that is the qestion...)
But let see at the output:
service# dladm show-vnic LINK OVER SPEED MACADDRESS MACADDRTYPE VID vn2 sw0 0 2:8:20:62:94:da random 0 vn2 sw0 0 2:8:20:20:79:9d random 0
Now let destroy it:
service# dladm delete-vnic vn2;echo $? 0 service# dladm show-vnic LINK OVER SPEED MACADDRESS MACADDRTYPE VID vn0 sw0 0 2:8:20:f:62:a6 random 0 vn2 sw0 0 2:8:20:62:94:da random 0
Well, done...
Now we stop the zone and try to create vnic once again:
service# zoneadm -z zhost02 halt service# dladm create-vnic -l sw0 vn2;echo $? dladm: vnic creation over sw0 failed: object already exists 1
and it works correctly.
I tried to debug dladm in gdb step by step, the problem is
dladm_door_call() from libdlmgmt.c returns DLADM_STATUS_OK
instead of DLADM_STATUS_EXIST in line 73: door_call(door_fd, &darg)
http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libdladm/common/libdlmgmt.c#73
by the way, the system is OI, it tested on two hosts.
Related issues
Updated by Ryan Zezeski almost 7 years ago
Believe it or not, this is functioning as designed -- but it's
certainly confusing if you don't know what's going on. And dladm's
interface is lacking the necessary information to understand what is
happening.
The dlmgmt daemon, which does the real work on behalf of dladm, has
the notion of zone-namespaced links -- i.e., a link's fully qualified
name is its zone identifier and vanity name (the vanity name is what
you see in dladm). When you boot the zone the link is "loaned" to the
zone and dlmgmtd changes the link's zoneid field to the id of the zone
that owns it. Then, when you create the second instance of the same
name dlmgmtd searches the GZ namespace for the link name and sees no
matches -- so it creates another. At this point you have two links
with the same name but assigned to different zones. However, dladm
doesn't really communicate this by say printing a ZONE column when
running show-link. There is a zone linkprop but if you show-linkprop I
think it only shows the link in the GZ. You can show-linkprop in the
NGZ but it doesn't seem to have the rights to view the zone property.
Basically, it feels like some of this work was still in an unfinished
state from the time illumos forked from OpenSolaris. There has been
some additional work done in SmartOS to better support namespaced
links but I'm not sure if a) it's complete yet or b) if it's the right
way to do it (I don't mean that in any negative way, simply that
there's probably a few ways to get this job done).
Anyways, I've been working on dladm and dlmgmtd in SmartOS lately. It
would be nice to make this less confusing in illumos-gate so everyone
can benefit. But I'm not sure what the first step is. I'll see if I
can get some ideas on my side. In the meantime, I hope this
explanation helped.
For further comprehension here is a dtrace script I cooked up to
demonstrate exactly what is happening. The first run is when the zone
is stopped, so the vnic already exists in the GZ. The second run is
when the zone is running, so the vnic exists in the NGZ, not the GZ
(pid 47 is dlmgmtd).
root@midgar:/root# dtrace -Fqn 'pid$target::dlmgmt_createid:entry { self->t = 1; } pid$target::dlmgmt_*:entry,pid$target::cmp_link*:entry /self->t/ { printf("\n"); } pid$target::dlmgmt_*:return,pid$target::cmp_link*:return /self->t/ { printf("%d (%p)\n", arg1, arg1); } pid$target::dlmgmt_createid:return /self->t/ { self->t = 0; }' -p 47 CPU FUNCTION 0 -> dlmgmt_createid 0 -> dlmgmt_table_lock 0 -> dlmgmt_table_readwritelock 0 <- dlmgmt_table_readwritelock 0 (0) 0 <- dlmgmt_table_lock 0 (0) 0 -> dlmgmt_checkprivs 0 <- dlmgmt_checkprivs 0 (0) 0 -> dlmgmt_create_common 0 -> cmp_link_by_zname 0 -> cmp_link_by_name 0 <- cmp_link_by_name 1 (1) 0 <- cmp_link_by_zname 1 (1) 0 -> cmp_link_by_zname 0 -> cmp_link_by_name 0 <- cmp_link_by_name 0 (0) 0 <- cmp_link_by_zname 0 (0) 0 <- dlmgmt_create_common 17 (11) 0 -> dlmgmt_table_unlock 0 <- dlmgmt_table_unlock 0 (0) 0 <- dlmgmt_createid 0 (0) ^C root@midgar:/root# dtrace -Fqn 'pid$target::dlmgmt_createid:entry { self->t = 1; } pid$target::dlmgmt_*:entry,pid$target::cmp_link*:entry /self->t/ { printf("\n"); } pid$target::dlmgmt_*:return,pid$target::cmp_link*:return /self->t/ { printf("%d (%p)\n", arg1, arg1); } pid$target::dlmgmt_createid:return /self->t/ { self->t = 0; }' -p 47 CPU FUNCTION 1 -> dlmgmt_createid 1 -> dlmgmt_table_lock 1 -> dlmgmt_table_readwritelock 1 <- dlmgmt_table_readwritelock 0 (0) 1 <- dlmgmt_table_lock 0 (0) 1 -> dlmgmt_checkprivs 1 <- dlmgmt_checkprivs 0 (0) 1 -> dlmgmt_create_common 1 -> cmp_link_by_zname 1 -> cmp_link_by_name 1 <- cmp_link_by_name 1 (1) 1 <- cmp_link_by_zname 1 (1) 1 -> cmp_link_by_zname 1 <- cmp_link_by_zname 4294967295 (ffffffff) 1 -> cmp_link_by_id 1 <- cmp_link_by_id 1 (1) 1 -> cmp_link_by_id 1 <- cmp_link_by_id 1 (1) 1 -> dlmgmt_advance 1 -> dlmgmt_advance_linkid 1 <- dlmgmt_advance_linkid 0 (0) 1 -> dlmgmt_advance_ppa 1 <- dlmgmt_advance_ppa 8 (8) 1 <- dlmgmt_advance 8 (8) 1 <- dlmgmt_create_common 0 (0) 1 -> dlmgmt_write_db_entry 1 -> dlmgmt_db_update 1 -> dlmgmt_db_req_alloc 1 <- dlmgmt_db_req_alloc 134663480 (806cd38) 1 -> dlmgmt_process_db_req 1 -> dlmgmt_process_db_onereq 1 -> dlmgmt_zfopen 1 -> dlmgmt_zfop 1 -> dlmgmt_zopen_cb 1 <- dlmgmt_zopen_cb 0 (0) 1 <- dlmgmt_zfop 0 (0) 1 <- dlmgmt_zfopen 134657968 (806b7b0) 1 -> dlmgmt_zfopen 1 -> dlmgmt_zfop 1 -> dlmgmt_zopen_cb 1 <- dlmgmt_zopen_cb 0 (0) 1 <- dlmgmt_zfop 0 (0) 1 <- dlmgmt_zfopen 134657984 (806b7c0) 1 -> cmp_link_by_id 1 <- cmp_link_by_id 1 (1) 1 -> cmp_link_by_id 1 <- cmp_link_by_id 1 (1) 1 -> cmp_link_by_id 1 <- cmp_link_by_id 0 (0) 1 -> dlmgmt_zrename 1 -> dlmgmt_zfop 1 -> dlmgmt_zrename_cb 1 <- dlmgmt_zrename_cb 0 (0) 1 <- dlmgmt_zfop 0 (0) 1 <- dlmgmt_zrename 0 (0) 1 <- dlmgmt_process_db_onereq 0 (0) 1 <- dlmgmt_process_db_req 0 (0) 1 <- dlmgmt_db_update 0 (0) 1 <- dlmgmt_write_db_entry 0 (0) 1 -> dlmgmt_table_unlock 1 <- dlmgmt_table_unlock 0 (0) 1 <- dlmgmt_createid 4 (4) ^C
Updated by Andy Fiddaman almost 5 years ago
- Related to Bug #10001: creating duplicate vnics is possible, and breaks dladm added