For stable bridge configuration, sometimes it is desirable to be able to
add-port with port number specified.
This patch implements it and it can be done by setting ofport column of 
Interface
table like

  ovs-vsctl add-port s1 eth2 -- set Interface eth2 ofport=10

Signed-off-by: Isaku Yamahata <yamah...@valinux.co.jp>
---
 ofproto/ofproto-dpif.c |    2 +-
 ofproto/ofproto.c      |    2 +-
 tests/ovs-vsctl.at     |   29 +++++++++++++++++++++++++++++
 vswitchd/bridge.c      |   39 +++++++++++++++++++++++++++------------
 4 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index dcdd8f2..0bba0ec 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -2531,7 +2531,7 @@ static int
 port_add(struct ofproto *ofproto_, struct netdev *netdev, uint16_t *ofp_portp)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
-    uint16_t odp_port = UINT16_MAX;
+    uint16_t odp_port = ofp_port_to_odp_port(*ofp_portp);
     int error;
 
     error = dpif_port_add(ofproto->dpif, netdev, &odp_port);
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index b87b6e7..25b1824 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -1353,7 +1353,7 @@ int
 ofproto_port_add(struct ofproto *ofproto, struct netdev *netdev,
                  uint16_t *ofp_portp)
 {
-    uint16_t ofp_port;
+    uint16_t ofp_port = ofp_portp ? *ofp_portp : OFPP_NONE;
     int error;
 
     error = ofproto->ofproto_class->port_add(ofproto, netdev, &ofp_port);
diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
index e903619..00e37cc 100644
--- a/tests/ovs-vsctl.at
+++ b/tests/ovs-vsctl.at
@@ -1096,3 +1096,32 @@ AT_CHECK([RUN_OVS_VSCTL(
    [-- list Queue])], [0], [], [], [OVS_VSCTL_CLEANUP])
 OVS_VSCTL_CLEANUP
 AT_CLEANUP
+
+dnl ----------------------------------------------------------------------
+AT_BANNER([ovs-vsctl unit tests --- add-port with port no specified])
+
+AT_SETUP([add-br a, add-port a a1, set Interface a ofport=10])
+AT_KEYWORDS([ovs-vsctl port-no])
+OVS_VSCTL_SETUP
+AT_CHECK([RUN_OVS_VSCTL([add-br a])], [0], [], [], [OVS_VSCTL_CLEANUP])
+CHECK_BRIDGES([a, a, 0])
+AT_CHECK([RUN_OVS_VSCTL([add-port a a0])], [0], [], [], [OVS_VSCTL_CLEANUP])
+CHECK_BRIDGES([a, a, 0])
+CHECK_PORTS([a], [a0])
+CHECK_IFACES([a], [a0])
+AT_CHECK([RUN_OVS_VSCTL(get Interface a0 ofport)], [0], [[[]
+]], [], [OVS_VSCTL_CLEANUP])
+AT_CHECK([RUN_OVS_VSCTL([del-port a a0])], [0], [], [], [OVS_VSCTL_CLEANUP])
+
+AT_CHECK([RUN_OVS_VSCTL_TOGETHER(
+   [add-port a a1],
+   [set Interface a1 ofport=10])], [0], [
+
+], [], [OVS_VSCTL_CLEANUP])
+CHECK_PORTS([a], [a1])
+CHECK_IFACES([a], [a1])
+AT_CHECK([RUN_OVS_VSCTL(get Interface a1 ofport)], [0], [10
+], [], [OVS_VSCTL_CLEANUP])
+AT_CHECK([RUN_OVS_VSCTL([del-port a a1])], [0], [], [], [OVS_VSCTL_CLEANUP])
+OVS_VSCTL_CLEANUP
+AT_CLEANUP
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 940e5e7..e98ac57 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -65,6 +65,8 @@ COVERAGE_DEFINE(bridge_reconfigure);
 struct if_cfg {
     struct hmap_node hmap_node;         /* Node in bridge's if_cfg_todo. */
     const struct ovsrec_interface *cfg; /* Interface record. */
+    int64_t ofport;                     /* requested ofport. OFPP_NONE means
+                                           auto-allocate ofport */
     const struct ovsrec_port *parent;   /* Parent port record. */
 };
 
@@ -225,7 +227,8 @@ static bool mirror_configure(struct mirror *);
 static void mirror_refresh_stats(struct mirror *);
 
 static void iface_configure_lacp(struct iface *, struct lacp_slave_settings *);
-static bool iface_create(struct bridge *, struct if_cfg *, int ofp_port);
+static bool iface_create(struct bridge *, struct if_cfg *,
+                         int ofp_port, bool allocate_port);
 static const char *iface_get_type(const struct ovsrec_interface *,
                                   const struct ovsrec_bridge *);
 static void iface_destroy(struct iface *);
@@ -495,7 +498,7 @@ bridge_reconfigure_ofp(void)
         struct if_cfg *if_cfg, *next;
 
         HMAP_FOR_EACH_SAFE (if_cfg, next, hmap_node, &br->if_cfg_todo) {
-            iface_create(br, if_cfg, -1);
+            iface_create(br, if_cfg, if_cfg->ofport, true);
             time_refresh();
             if (time_msec() >= deadline) {
                 return false;
@@ -1205,9 +1208,14 @@ bridge_refresh_one_ofp_port(struct bridge *br,
          * and add it.  If that's successful, we'll keep it.  Otherwise, we'll
          * delete it and later try to re-add it. */
         struct if_cfg *if_cfg = if_cfg_lookup(br, name);
+        bool allocate_port = false;
+        if (ofp_port < 0) {
+            ofp_port = OFPP_NONE;
+            allocate_port = true;
+        }
         return (if_cfg
                 && !strcmp(type, iface_get_type(if_cfg->cfg, br->cfg))
-                && iface_create(br, if_cfg, ofp_port));
+                && iface_create(br, if_cfg, ofp_port, allocate_port));
     }
 }
 
@@ -1260,8 +1268,8 @@ bridge_refresh_ofp_port(struct bridge *br)
     }
 }
 
-/* Opens a network device for 'iface_cfg' and configures it.  If '*ofp_portp'
- * is negative, adds the network device to br->ofproto and stores the OpenFlow
+/* Opens a network device for 'iface_cfg' and configures it.  If allocate_port
+ * is true, adds the network device to br->ofproto and stores the OpenFlow
  * port number in '*ofp_portp'; otherwise leaves br->ofproto and '*ofp_portp'
  * untouched.
  *
@@ -1271,7 +1279,8 @@ static int
 iface_do_create(const struct bridge *br,
                 const struct ovsrec_interface *iface_cfg,
                 const struct ovsrec_port *port_cfg,
-                int *ofp_portp, struct netdev **netdevp)
+                int *ofp_portp, bool allocate_port,
+                struct netdev **netdevp)
 {
     struct netdev *netdev;
     int error;
@@ -1289,9 +1298,8 @@ iface_do_create(const struct bridge *br,
         goto error;
     }
 
-    if (*ofp_portp < 0) {
-        uint16_t ofp_port;
-
+    if (allocate_port) {
+        uint16_t ofp_port = *ofp_portp;
         error = ofproto_port_add(br->ofproto, netdev, &ofp_port);
         if (error) {
             goto error;
@@ -1319,13 +1327,14 @@ error:
 }
 
 /* Creates a new iface on 'br' based on 'if_cfg'.  The new iface has OpenFlow
- * port number 'ofp_port'.  If ofp_port is negative, an OpenFlow port is
+ * port number 'ofp_port'. If create is true, an OpenFlow port is
  * automatically allocated for the iface.  Takes ownership of and
  * deallocates 'if_cfg'.
  *
  * Return true if an iface is successfully created, false otherwise. */
 static bool
-iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port)
+iface_create(struct bridge *br, struct if_cfg *if_cfg,
+             int ofp_port, bool allocate_port)
 {
     const struct ovsrec_interface *iface_cfg = if_cfg->cfg;
     const struct ovsrec_port *port_cfg = if_cfg->parent;
@@ -1347,7 +1356,8 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, 
int ofp_port)
      * additions and deletions are cheaper, these calls should be removed. */
     bridge_run_fast();
     assert(!iface_lookup(br, iface_cfg->name));
-    error = iface_do_create(br, iface_cfg, port_cfg, &ofp_port, &netdev);
+    error = iface_do_create(br, iface_cfg, port_cfg, &ofp_port, allocate_port,
+                            &netdev);
     bridge_run_fast();
     if (error) {
         iface_clear_db_record(iface_cfg);
@@ -2450,6 +2460,11 @@ bridge_queue_if_cfg(struct bridge *br,
 
     if_cfg->cfg = cfg;
     if_cfg->parent = parent;
+    if_cfg->ofport = OFPP_NONE;
+    if (cfg->n_ofport > 0 &&
+        (0 <= cfg->ofport[0] && cfg->ofport[0] <= OFPP_MAX)) {
+        if_cfg->ofport = cfg->ofport[0];
+    }
     hmap_insert(&br->if_cfg_todo, &if_cfg->hmap_node,
                 hash_string(if_cfg->cfg->name, 0));
 }
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to