xenserver: Send VIF details to controller
authorJustin Pettit <jpettit@nicira.com>
Wed, 10 Jun 2009 01:19:02 +0000 (18:19 -0700)
committerJustin Pettit <jpettit@nicira.com>
Wed, 10 Jun 2009 01:22:24 +0000 (18:22 -0700)
The controller needs to know various things about virtual interfaces as
they move about the network.  This commit sends the VIF, virtual
machine, and network UUIDs associated with the VIF, as well as its MAC
address over the management channel.

Feature #1324

include/openflow/openflow-mgmt.h
vswitchd/mgmt.c
xenserver/README
xenserver/etc_xensource_scripts_vif
xenserver/root_vswitch_scripts_dump-vif-details [new file with mode: 0755]
xenserver/vswitch-xen.spec

index c780942..c900c18 100644 (file)
@@ -96,7 +96,7 @@ OFP_ASSERT(sizeof(struct ofmptsr_dp) == 32);
  */
 #define OFMP_UUID_LEN 36
 
-/* Resource TLV for UUIDs associated with this datapath. */
+/* Resource TLV for XenServer UUIDs associated with this datapath. */
 struct ofmptsr_dp_uuid {
     uint16_t type;                        /* OFMPTSR_DP_UUID. */
     uint16_t len;                         /* Length. */
@@ -107,7 +107,9 @@ struct ofmptsr_dp_uuid {
 };
 OFP_ASSERT(sizeof(struct ofmptsr_dp_uuid) == 16);
 
-/* Resource TLV for UUID associated with this managment instance. */
+/* Resource TLV for XenServer UUID associated with this managment 
+ * instance. 
+ */
 struct ofmptsr_mgmt_uuid {
     uint16_t type;                        /* OFMPTSR_MGMT_UUID. */
     uint16_t len;                         /* 52. */
@@ -118,12 +120,25 @@ struct ofmptsr_mgmt_uuid {
 };
 OFP_ASSERT(sizeof(struct ofmptsr_mgmt_uuid) == 56);
 
+/* Resource TLV for details about this XenServer vif. */
+struct ofmptsr_vif {
+    uint16_t type;                        /* OFMPTSR_VIF. */
+    uint16_t len;                         /* 136. */
+    uint8_t name[OFP_MAX_PORT_NAME_LEN];  /* Null-terminated name. */
+    uint8_t vif_uuid[OFMP_UUID_LEN];      /* VIF UUID. */
+    uint8_t vm_uuid[OFMP_UUID_LEN];       /* VM UUID. */
+    uint8_t net_uuid[OFMP_UUID_LEN];      /* Network UUID. */
+    uint64_t vif_mac;                     /* Management ID. */
+};
+OFP_ASSERT(sizeof(struct ofmptsr_vif) == 136);
+
 /* TLV types for switch resource descriptions. */
 enum ofmp_switch_resources {
     OFMPTSR_END = 0,                      /* Terminator. */
     OFMPTSR_DP,                           /* Datapath. */
     OFMPTSR_DP_UUID,                      /* Xen: datapath uuid's. */
     OFMPTSR_MGMT_UUID,                    /* Xen: management uuid. */
+    OFMPTSR_VIF,                          /* Xen: vif details. */
 };
 
 /* Body of resources request.
index b31d141..90f3ecb 100644 (file)
@@ -306,6 +306,7 @@ send_resources_update(uint32_t xid, bool use_xid)
     struct ofmp_resources_update *ofmpru;
     struct ofmp_tlv *tlv;
     struct svec br_list;
+    struct svec port_list;
     const char *host_uuid;
     int i;
 
@@ -381,6 +382,48 @@ send_resources_update(uint32_t xid, bool use_xid)
         }
     }
 
+    /* On XenServer systems, extended information about virtual interfaces 
+     * (VIFs) is available, which is needed by the controller. 
+     */ 
+    svec_init(&port_list);
+    bridge_get_ifaces(&port_list);
+    for (i=0; i < port_list.n; i++) {
+        const char *vif_uuid, *vm_uuid, *net_uuid;
+        uint64_t vif_mac;
+        struct ofmptsr_vif *vif_tlv;
+
+        vif_uuid = cfg_get_string(0, "port.%s.vif-uuid", port_list.names[i]);
+        if (!vif_uuid) {
+            continue;
+        }
+
+        vif_tlv = ofpbuf_put_zeros(buffer, sizeof(*vif_tlv));
+        vif_tlv->type = htons(OFMPTSR_VIF);
+        vif_tlv->len = htons(sizeof(*vif_tlv));
+
+        memcpy(vif_tlv->name, port_list.names[i], strlen(port_list.names[i])+1);
+        memcpy(vif_tlv->vif_uuid, vif_uuid, sizeof(vif_tlv->vif_uuid));
+
+        vm_uuid = cfg_get_string(0, "port.%s.vm-uuid", port_list.names[i]);
+        if (vm_uuid) {
+            memcpy(vif_tlv->vm_uuid, vm_uuid, sizeof(vif_tlv->vm_uuid));
+        } else {
+            /* In case the vif disappeared underneath us. */
+            memset(vif_tlv->vm_uuid, '\0', sizeof(vif_tlv->vm_uuid));
+        }
+
+        net_uuid = cfg_get_string(0, "port.%s.net-uuid", port_list.names[i]);
+        if (net_uuid) {
+            memcpy(vif_tlv->net_uuid, net_uuid, sizeof(vif_tlv->net_uuid));
+        } else {
+            /* In case the vif disappeared underneath us. */
+            memset(vif_tlv->net_uuid, '\0', sizeof(vif_tlv->net_uuid));
+        }
+
+        vif_mac = cfg_get_mac(0, "port.%s.vif-mac", port_list.names[i]);
+        vif_tlv->vif_mac = htonll(vif_mac);
+    }
+
     /* Put end marker. */
     tlv = ofpbuf_put_zeros(buffer, sizeof(*tlv));
     tlv->type = htons(OFMPTSR_END);
index 7cd04ab..2344835 100644 (file)
@@ -48,6 +48,12 @@ files are:
 
         vswitch-aware replacement for Citrix script of the same name.
 
+    root_vswitch_scripts_dump-vif-details
+
+        Script to retrieve extended information about VIFs that are
+        needed by the controller.  This is called by the "vif" script,
+        which is run when virtual interfaces are added and removed.
+
     usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py
 
         xsconsole plugin to configure the pool-wide configuration keys
index fcf13a6..796da99 100755 (executable)
@@ -14,6 +14,7 @@
 # Keep other-config/ keys in sync with device.ml:vif_udev_keys
 
 cfg_mod="/root/vswitch/bin/ovs-cfg-mod"
+dump_vif_details="/root/vswitch/scripts/dump-vif-details"
 service="/sbin/service"
 
 TYPE=`echo ${XENBUS_PATH} | cut -f 2 -d '/'`
@@ -86,12 +87,17 @@ add_to_bridge()
     ${IP} link set "${vif}" address "${address}"        || logger -t scripts-vif "Failed to ip link set ${vif} address ${address}"
     ${IP} addr flush "${vif}"                           || logger -t scripts-vif "Failed to ip addr flush ${vif}"
 
+    local vif_details=$($dump_vif_details $DOMID $DEVID)
+    if [ $? -ne 0 -o -z "${vif_details}" ]; then
+           logger -t scripts-vif "Failed to retrieve vif details for vswitch"
+    fi
+
     $cfg_mod -F /etc/ovs-vswitchd.conf \
         --del-match="bridge.*.port=$vif" \
         --del-match="vlan.$vif.[!0-9]*" \
         --del-match="port.$vif.[!0-9]*" \
         --add="bridge.$bridge.port=$vif" \
-        $vid -c
+        $vid $vif_details -c >/tmp/j
     $service vswitch reload
 
     ${IP} link set "${vif}" up                          || logger -t scripts-vif "Failed to ip link set ${vif} up"
diff --git a/xenserver/root_vswitch_scripts_dump-vif-details b/xenserver/root_vswitch_scripts_dump-vif-details
new file mode 100755 (executable)
index 0000000..2e9aa03
--- /dev/null
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+#
+# Script to retrieve extended information about VIFs that are
+# needed by the controller.  This is called by the "vif" script,
+# which is run when virtual interfaces are added and removed.
+
+# Copyright (C) 2009 Nicira Networks, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without warranty of any kind.
+
+import sys
+import XenAPI
+import xen.lowlevel.xs
+
+# Query XenStore for the opaque reference of this vif
+def get_vif_ref(domid, devid):
+       xenstore = xen.lowlevel.xs.xs()
+       t = xenstore.transaction_start()
+       vif_ref = xenstore.read(t, '/xapi/%s/private/vif/%s/ref' % (domid, devid))
+       xenstore.transaction_end(t)
+       return vif_ref
+
+# Query XAPI for the information we need using the vif's opaque reference
+def dump_vif_info(domid, devid, vif_ref):
+       try: 
+               session = XenAPI.xapi_local()
+               session.xenapi.login_with_password("root", "")
+               vif_rec = session.xenapi.VIF.get_record(vif_ref)
+               net_rec = session.xenapi.network.get_record(vif_rec["network"])
+               vm_rec = session.xenapi.VM.get_record(vif_rec["VM"])
+
+               sys.stdout.write('--add=port.vif%s.%s.network-uuid=%s ' 
+                               % (domid, devid, net_rec["uuid"]))
+               sys.stdout.write('--add=port.vif%s.%s.vif-mac=%s ' 
+                               % (domid, devid, vif_rec["MAC"]))
+               sys.stdout.write('--add=port.vif%s.%s.vif-uuid=%s ' 
+                               % (domid, devid, vif_rec["uuid"]))
+               sys.stdout.write('--add=port.vif%s.%s.vm-uuid=%s ' 
+                               % (domid, devid, vm_rec["uuid"]))
+       finally:
+               session.xenapi.session.logout()
+       
+if __name__ == '__main__':
+       if (len(sys.argv) != 3):
+               sys.stderr.write("ERROR: %s <domid> <devid>\n")
+               sys.exit(1)
+
+       domid = sys.argv[1]
+       devid = sys.argv[2]
+
+       vif_ref = get_vif_ref(domid, devid)
+       if not vif_ref:
+               sys.stderr.write("ERROR: Could not find interface vif%s.%s\n" 
+                               % (domid, devid))
+               sys.exit(1)
+
+       dump_vif_info(domid, devid, vif_ref)
+       sys.exit(0)
index fc9b6d2..ee3fce3 100644 (file)
@@ -65,6 +65,8 @@ install -m 755 xenserver/opt_xensource_libexec_interface-reconfigure \
              $RPM_BUILD_ROOT%{_prefix}/scripts/interface-reconfigure
 install -m 755 xenserver/etc_xensource_scripts_vif \
              $RPM_BUILD_ROOT%{_prefix}/scripts/vif
+install -m 755 xenserver/root_vswitch_scripts_dump-vif-details \
+               $RPM_BUILD_ROOT%{_prefix}/scripts/dump-vif-details
 install -m 755 \
         xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py \
                $RPM_BUILD_ROOT%{_prefix}/scripts/XSFeatureVSwitch.py
@@ -286,6 +288,7 @@ fi
 /root/vswitch/kernel_modules/brcompat_mod.ko
 /root/vswitch/kernel_modules/openvswitch_mod.ko
 /root/vswitch/kernel_modules/veth_mod.ko
+/root/vswitch/scripts/dump-vif-details
 /root/vswitch/scripts/interface-reconfigure
 /root/vswitch/scripts/vif
 /root/vswitch/scripts/XSFeatureVSwitch.py