Option to forward BPDU (Ethernet control class) frames
[sliver-openvswitch.git] / vswitchd / bridge.c
index 9b70e63..d99d6a1 100644 (file)
@@ -150,6 +150,7 @@ static void bridge_refresh_ofp_port(struct bridge *);
 static void bridge_configure_datapath_id(struct bridge *);
 static void bridge_configure_flow_eviction_threshold(struct bridge *);
 static void bridge_configure_netflow(struct bridge *);
+static void bridge_configure_forward_bpdu(struct bridge *);
 static void bridge_configure_sflow(struct bridge *, int *sflow_bridge_number);
 static void bridge_configure_remotes(struct bridge *,
                                      const struct sockaddr_in *managers,
@@ -414,6 +415,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
         bridge_configure_mirrors(br);
         bridge_configure_datapath_id(br);
         bridge_configure_flow_eviction_threshold(br);
+        bridge_configure_forward_bpdu(br);
         bridge_configure_remotes(br, managers, n_managers);
         bridge_configure_netflow(br);
         bridge_configure_sflow(br, &sflow_bridge_number);
@@ -846,28 +848,36 @@ bridge_add_ofproto_ports(struct bridge *br)
         struct ofproto_port ofproto_port;
 
         LIST_FOR_EACH_SAFE (iface, next_iface, port_elem, &port->ifaces) {
-            struct shash args;
             int error;
 
-            /* Open the netdev or reconfigure it. */
-            shash_init(&args);
-            shash_from_ovs_idl_map(iface->cfg->key_options,
-                                   iface->cfg->value_options,
-                                   iface->cfg->n_options, &args);
+            /* Open the netdev. */
             if (!iface->netdev) {
-                struct netdev_options options;
-                options.name = iface->name;
-                options.type = iface->type;
-                options.args = &args;
-                error = netdev_open(&options, &iface->netdev);
+                error = netdev_open(iface->name, iface->type, &iface->netdev);
+                if (error) {
+                    VLOG_WARN("could not open network device %s (%s)",
+                              iface->name, strerror(error));
+                }
             } else {
-                error = netdev_set_config(iface->netdev, &args);
+                error = 0;
             }
-            shash_destroy(&args);
-            if (error) {
-                VLOG_WARN("could not %s network device %s (%s)",
-                          iface->netdev ? "reconfigure" : "open",
-                          iface->name, strerror(error));
+
+            /* Configure the netdev. */
+            if (iface->netdev) {
+                struct shash args;
+
+                shash_init(&args);
+                shash_from_ovs_idl_map(iface->cfg->key_options,
+                                       iface->cfg->value_options,
+                                       iface->cfg->n_options, &args);
+                error = netdev_set_config(iface->netdev, &args);
+                shash_destroy(&args);
+
+                if (error) {
+                    VLOG_WARN("could not configure network device %s (%s)",
+                              iface->name, strerror(error));
+                    netdev_close(iface->netdev);
+                    iface->netdev = NULL;
+                }
             }
 
             /* Add the port, if necessary. */
@@ -891,7 +901,7 @@ bridge_add_ofproto_ports(struct bridge *br)
                 iface_refresh_status(iface);
             }
 
-            /* Delete the iface if  */
+            /* Delete the iface if we failed. */
             if (iface->netdev && iface->ofp_port >= 0) {
                 VLOG_DBG("bridge %s: interface %s is on port %d",
                          br->name, iface->name, iface->ofp_port);
@@ -917,14 +927,10 @@ bridge_add_ofproto_ports(struct bridge *br)
         if (port_is_bond_fake_iface(port)) {
             if (ofproto_port_query_by_name(br->ofproto, port->name,
                                            &ofproto_port)) {
-                struct netdev_options options;
                 struct netdev *netdev;
                 int error;
 
-                options.name = port->name;
-                options.type = "internal";
-                options.args = NULL;
-                error = netdev_open(&options, &netdev);
+                error = netdev_open(port->name, "internal", &netdev);
                 if (!error) {
                     ofproto_port_add(br->ofproto, netdev, NULL);
                     netdev_close(netdev);
@@ -978,6 +984,20 @@ bridge_configure_flow_eviction_threshold(struct bridge *br)
     ofproto_set_flow_eviction_threshold(br->ofproto, threshold);
 }
 
+/* Set forward BPDU option. */
+static void
+bridge_configure_forward_bpdu(struct bridge *br)
+{
+    const char *forward_bpdu_str;
+    bool forward_bpdu = false;
+
+    forward_bpdu_str = bridge_get_other_config(br->cfg, "forward-bpdu");
+    if (forward_bpdu_str && !strcmp(forward_bpdu_str, "true")) {
+        forward_bpdu = true;
+    }
+    ofproto_set_forward_bpdu(br->ofproto, forward_bpdu);
+}
+
 static void
 bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
                           struct iface **hw_addr_iface)