[ovs-dev] [PATCH] bfd: Optimize BFD for Megaflows.

Gurucharan Shetty shettyg at nicira.com
Mon Aug 5 07:47:36 UTC 2013


The current situation is that whenever any packet enters the
userspace, bfd_should_process_flow() looks at the UDP destination
port to figure out whether that is a BFD packet. This means that
UDP destination port cannot be wildcarded for all the other flows
too.

To optimize BFD for megaflows, we introduce a new
'bfd:bfd_dst_mac' field in the database. Whenever this field is set
by a controller, it is assumed that all the BFD packets to/from
this interface will have the destination mac address set as the one
specified in the bfd:bfd_dst_mac field. If this field is set, we
first look at the destination mac address of a packet and if it
does not match the mac address set in bfd:bfd_dst_mac, we do not
process that packet as bfd. If the field does match, we go ahead
and look at the UDP destination port too.

Also, change the default BFD destination mac address to
"00:23:20:00:00:01".

Feature #18850.
Signed-off-by: Gurucharan Shetty <gshetty at nicira.com>
---
 lib/bfd.c            |   27 +++++++++++++++++++++++++--
 lib/bfd.h            |    1 +
 vswitchd/vswitch.xml |    9 +++++++++
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/lib/bfd.c b/lib/bfd.c
index f2d4b9c..668c0a1 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -161,6 +161,9 @@ struct bfd {
 
     uint32_t rmt_disc;            /* bfd.RemoteDiscr. */
 
+    uint8_t eth_dst[ETH_ADDR_LEN];/* Ethernet destination address. */
+    bool eth_dst_set;             /* 'eth_dst' set through database. */
+
     uint16_t udp_src;             /* UDP source port. */
 
     /* All timers in milliseconds. */
@@ -259,6 +262,8 @@ bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg)
 
     long long int min_tx, min_rx;
     bool cpath_down;
+    const char *hwaddr;
+    uint8_t ea[ETH_ADDR_LEN];
 
     if (ovsthread_once_start(&once)) {
         unixctl_command_register("bfd/show", "[interface]", 0, 1,
@@ -296,6 +301,9 @@ bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg)
         bfd->udp_src = (bfd->udp_src % 16384) + 49152;
 
         bfd_set_state(bfd, STATE_DOWN, DIAG_NONE);
+
+        eth_addr_from_string(BFD_ETH_DST, ea);
+        memcpy(bfd->eth_dst, ea, ETH_ADDR_LEN);
     }
 
     atomic_store(&bfd->check_tnl_key,
@@ -330,6 +338,17 @@ bfd_configure(struct bfd *bfd, const char *name, const struct smap *cfg)
         }
         bfd_poll(bfd);
     }
+
+    hwaddr = smap_get(cfg, "bfd_dst_mac");
+    if (hwaddr && eth_addr_from_string(hwaddr, ea) && !eth_addr_is_zero(ea)) {
+        memcpy(bfd->eth_dst, ea, ETH_ADDR_LEN);
+        bfd->eth_dst_set = true;
+    } else if (bfd->eth_dst_set) {
+        eth_addr_from_string(BFD_ETH_DST, ea);
+        memcpy(bfd->eth_dst, ea, ETH_ADDR_LEN);
+        bfd->eth_dst_set = false;
+    }
+
     ovs_mutex_unlock(&mutex);
     return bfd;
 }
@@ -430,8 +449,8 @@ bfd_put_packet(struct bfd *bfd, struct ofpbuf *p,
 
     ofpbuf_reserve(p, 2); /* Properly align after the ethernet header. */
     eth = ofpbuf_put_uninit(p, sizeof *eth);
-    memcpy(eth->eth_dst, eth_addr_broadcast, ETH_ADDR_LEN);
     memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN);
+    memcpy(eth->eth_dst, bfd->eth_dst, ETH_ADDR_LEN);
     eth->eth_type = htons(ETH_TYPE_IP);
 
     ip = ofpbuf_put_zeros(p, sizeof *ip);
@@ -483,6 +502,10 @@ bfd_should_process_flow(const struct bfd *bfd, const struct flow *flow,
                         struct flow_wildcards *wc)
 {
     bool check_tnl_key;
+    memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
+    if (bfd->eth_dst_set && memcmp(bfd->eth_dst, flow->dl_dst, ETH_ADDR_LEN)) {
+        return false;
+    }
 
     memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
     memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
@@ -493,7 +516,7 @@ bfd_should_process_flow(const struct bfd *bfd, const struct flow *flow,
     }
     return (flow->dl_type == htons(ETH_TYPE_IP)
             && flow->nw_proto == IPPROTO_UDP
-            && flow->tp_dst == htons(3784)
+            && flow->tp_dst == htons(BFD_DEST_PORT)
             && (check_tnl_key || flow->tunnel.tun_id == htonll(0)));
 }
 
diff --git a/lib/bfd.h b/lib/bfd.h
index 67d012e..cf6a46f 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -16,6 +16,7 @@
 #define BFD_H 1
 
 #define BFD_PACKET_LEN 24
+#define BFD_ETH_DST "00:23:20:00:00:01"
 #define BFD_DEST_PORT 3784
 
 #include <stdbool.h>
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 957b02c..b89d58c 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -1896,6 +1896,15 @@
           <code>false</code>.
       </column>
 
+      <column name="bfd" key="bfd_dst_mac">
+        An Ethernet address in the form
+        <var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>
+        to set the destination mac address of the bfd packet. If this
+        field is set, it is assumed that all the bfd packets destined to this
+        interface also has the same destination mac address. If not set, a
+        default value of <code>00:23:20:00:00:01</code> is used.
+      </column>
+
       <column name="bfd_status" key="state"
           type='{"type": "string",
           "enum": ["set", ["admin_down", "down", "init", "up"]]}'>
-- 
1.7.9.5




More information about the dev mailing list