ofproto-dpif: Use send_packet() instead of netdev_send().
authorJesse Gross <jesse@nicira.com>
Sun, 23 Oct 2011 00:22:11 +0000 (17:22 -0700)
committerJesse Gross <jesse@nicira.com>
Wed, 2 Nov 2011 23:36:49 +0000 (16:36 -0700)
netdev_send() directly sends a packet using Linux mechanisms, skipping
our kernel module. Several upper layer abstractions are built on top of
the kernel module, so this means that we loose stats, sFlow, etc. on
these packets. This changes bonding, LACP, and STP to use send_packet()
as CFM does, which uses the standard kernel mechanisms and provides a
single place that needs to be updated.

lib/bond.c
lib/bond.h
ofproto/ofproto-dpif.c

index 73ee814cd5f92a62a9f15236edc77702c4158c17..2b99b9acc5eb0c1a1f27503ceb33af62781324c8 100644 (file)
@@ -484,14 +484,15 @@ bond_wait(struct bond *bond)
 static bool
 may_send_learning_packets(const struct bond *bond)
 {
-    return !bond->lacp_negotiated && bond->balance != BM_AB;
+    return !bond->lacp_negotiated && bond->balance != BM_AB &&
+           bond->active_slave;
 }
 
 /* Returns true if 'bond' needs the client to send out packets to assist with
  * MAC learning on 'bond'.  If this function returns true, then the client
  * should iterate through its MAC learning table for the bridge on which 'bond'
  * is located.  For each MAC that has been learned on a port other than 'bond',
- * it should call bond_send_learning_packet().
+ * it should call bond_compose_learning_packet().
  *
  * This function will only return true if 'bond' is in SLB mode and LACP is not
  * negotiated.  Otherwise sending learning packets isn't necessary.
@@ -507,37 +508,33 @@ bond_should_send_learning_packets(struct bond *bond)
 
 /* Sends a gratuitous learning packet on 'bond' from 'eth_src' on 'vlan'.
  *
- * See bond_should_send_learning_packets() for description of usage. */
-int
-bond_send_learning_packet(struct bond *bond,
-                          const uint8_t eth_src[ETH_ADDR_LEN],
-                          uint16_t vlan)
+ * See bond_should_send_learning_packets() for description of usage. The
+ * caller should send the composed packet on the port associated with
+ * port_aux and takes ownership of the returned ofpbuf. */
+struct ofpbuf *
+bond_compose_learning_packet(struct bond *bond,
+                             const uint8_t eth_src[ETH_ADDR_LEN],
+                             uint16_t vlan, void **port_aux)
 {
     struct bond_slave *slave;
-    struct ofpbuf packet;
+    struct ofpbuf *packet;
     struct flow flow;
-    int error;
 
     assert(may_send_learning_packets(bond));
-    if (!bond->active_slave) {
-        /* Nowhere to send the learning packet. */
-        return 0;
-    }
 
     memset(&flow, 0, sizeof flow);
     memcpy(flow.dl_src, eth_src, ETH_ADDR_LEN);
     slave = choose_output_slave(bond, &flow, vlan);
 
-    ofpbuf_init(&packet, 0);
-    compose_benign_packet(&packet, "Open vSwitch Bond Failover", 0xf177,
+    packet = ofpbuf_new(0);
+    compose_benign_packet(packet, "Open vSwitch Bond Failover", 0xf177,
                           eth_src);
     if (vlan) {
-        eth_push_vlan(&packet, htons(vlan));
+        eth_push_vlan(packet, htons(vlan));
     }
-    error = netdev_send(slave->netdev, &packet);
-    ofpbuf_uninit(&packet);
 
-    return error;
+    *port_aux = slave->aux;
+    return packet;
 }
 \f
 /* Checks whether a packet that arrived on 'slave_' within 'bond', with an
index f95543269ed4f3566f4097fb62562360f2e7a3b4..195802983d4d126b7736c07e9129b83a47798684 100644 (file)
@@ -75,9 +75,9 @@ void bond_slave_set_may_enable(struct bond *, void *slave_, bool may_enable);
 
 /* Special MAC learning support for SLB bonding. */
 bool bond_should_send_learning_packets(struct bond *);
-int bond_send_learning_packet(struct bond *,
-                              const uint8_t eth_src[ETH_ADDR_LEN],
-                              uint16_t vlan);
+struct ofpbuf *bond_compose_learning_packet(struct bond *,
+                                            const uint8_t eth_src[ETH_ADDR_LEN],
+                                            uint16_t vlan, void **port_aux);
 
 /* Packet processing. */
 enum bond_verdict {
index 93e79a978d07ad6d8afbb5e8e381a380e2360939..9fdc489daf9f0d696cec342f777804cf55453947 100644 (file)
@@ -949,13 +949,8 @@ send_bpdu_cb(struct ofpbuf *pkt, int port_num, void *ofproto_)
             VLOG_WARN_RL(&rl, "%s: cannot send BPDU on port %d "
                          "with unknown MAC", ofproto->up.name, port_num);
         } else {
-            int error = netdev_send(ofport->up.netdev, pkt);
-            if (error) {
-                VLOG_WARN_RL(&rl, "%s: sending BPDU on port %s failed (%s)",
-                             ofproto->up.name,
-                             netdev_get_name(ofport->up.netdev),
-                             strerror(error));
-            }
+            send_packet(ofproto_dpif_cast(ofport->up.ofproto),
+                        ofport->odp_port, pkt);
         }
     }
     ofpbuf_delete(pkt);
@@ -1549,12 +1544,8 @@ send_pdu_cb(void *port_, const void *pdu, size_t pdu_size)
                                  pdu_size);
         memcpy(packet_pdu, pdu, pdu_size);
 
-        error = netdev_send(port->up.netdev, &packet);
-        if (error) {
-            VLOG_WARN_RL(&rl, "port %s: sending LACP PDU on iface %s failed "
-                         "(%s)", port->bundle->name,
-                         netdev_get_name(port->up.netdev), strerror(error));
-        }
+        send_packet(ofproto_dpif_cast(port->up.ofproto), port->odp_port,
+                    &packet);
         ofpbuf_uninit(&packet);
     } else {
         VLOG_ERR_RL(&rl, "port %s: cannot obtain Ethernet address of iface "
@@ -1573,7 +1564,16 @@ bundle_send_learning_packets(struct ofbundle *bundle)
     error = n_packets = n_errors = 0;
     LIST_FOR_EACH (e, lru_node, &ofproto->ml->lrus) {
         if (e->port.p != bundle) {
-            int ret = bond_send_learning_packet(bundle->bond, e->mac, e->vlan);
+            struct ofpbuf *learning_packet;
+            struct ofport_dpif *port;
+            int ret;
+
+            learning_packet = bond_compose_learning_packet(bundle->bond, e->mac,
+                                                           e->vlan,
+                                                           (void **)&port);
+            ret = send_packet(ofproto_dpif_cast(port->up.ofproto),
+                              port->odp_port, learning_packet);
+            ofpbuf_delete(learning_packet);
             if (ret) {
                 error = ret;
                 n_errors++;