[ovs-discuss] [PATCH 8/9] PROC: L3 in-band

Justin Pettit jpettit at nicira.com
Wed Jul 29 22:21:08 UTC 2009


---
 lib/dpif.c        |   22 +++++
 lib/dpif.h        |    2 +
 lib/netdev.c      |   40 --------
 lib/netdev.h      |    3 -
 secchan/in-band.c |  267 ++++++++++++++++++++++++++++++-----------------------
 secchan/in-band.h |    7 +-
 secchan/ofproto.c |   27 ++++-
 7 files changed, 203 insertions(+), 165 deletions(-)

diff --git a/lib/dpif.c b/lib/dpif.c
index 21f1173..323a7cf 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -322,6 +322,28 @@ dpif_port_query_by_name(const struct dpif *dpif, const char *devname,
     }
 }
 
+/* Looks up port number 'port_no' in 'dpif'.  On success, returns 0 and copies
+ * the port's name into the 'name_size' bytes in 'name', ensuring that the
+ * result is null-terminated.  On failure, returns a positive errno value and
+ * makes 'name' the empty string. */
+int
+dpif_port_get_name(struct dpif *dpif, uint16_t port_no,
+                   char *name, size_t name_size)
+{
+    struct odp_port port;
+    int error;
+
+    assert(name_size > 0);
+
+    error = dpif_port_query_by_number(dpif, port_no, &port);
+    if (!error) {
+        ovs_strlcpy(name, port.devname, name_size);
+    } else {
+        *name = '\0';
+    }
+    return error;
+}
+
 int
 dpif_port_list(const struct dpif *dpif,
                struct odp_port **ports, size_t *n_ports)
diff --git a/lib/dpif.h b/lib/dpif.h
index d81cf63..a098580 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -59,6 +59,8 @@ int dpif_port_query_by_number(const struct dpif *, uint16_t port_no,
                               struct odp_port *);
 int dpif_port_query_by_name(const struct dpif *, const char *devname,
                             struct odp_port *);
+int dpif_port_get_name(struct dpif *dpif, uint16_t port_no,
+                       char *name, size_t name_size);
 int dpif_port_list(const struct dpif *, struct odp_port **, size_t *n_ports);
 
 int dpif_port_group_set(struct dpif *, uint16_t group,
diff --git a/lib/netdev.c b/lib/netdev.c
index 912f88f..ca1a63d 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -987,46 +987,6 @@ netdev_turn_flags_off(struct netdev *netdev, enum netdev_flags flags,
     return do_update_flags(netdev, flags, 0, permanent);
 }
 
-/* Looks up the ARP table entry for 'ip' on 'netdev'.  If one exists and can be
- * successfully retrieved, it stores the corresponding MAC address in 'mac' and
- * returns 0.  Otherwise, it returns a positive errno value; in particular,
- * ENXIO indicates that there is not ARP table entry for 'ip' on 'netdev'. */
-int
-netdev_nodev_arp_lookup(const char *netdev_name, uint32_t ip, 
-                        uint8_t mac[ETH_ADDR_LEN]) 
-{
-    struct arpreq r;
-    struct sockaddr_in *pa;
-    int retval;
-
-    init_netdev();
-
-    memset(&r, 0, sizeof r);
-    pa = (struct sockaddr_in *) &r.arp_pa;
-    pa->sin_family = AF_INET;
-    pa->sin_addr.s_addr = ip;
-    pa->sin_port = 0;
-    r.arp_ha.sa_family = ARPHRD_ETHER;
-    r.arp_flags = 0;
-    strncpy(r.arp_dev, netdev_name, sizeof r.arp_dev);
-    COVERAGE_INC(netdev_arp_lookup);
-    retval = ioctl(af_inet_sock, SIOCGARP, &r) < 0 ? errno : 0;
-    if (!retval) {
-        memcpy(mac, r.arp_ha.sa_data, ETH_ADDR_LEN);
-    } else if (retval != ENXIO) {
-        VLOG_WARN_RL(&rl, "%s: could not look up ARP entry for "IP_FMT": %s",
-                     netdev_name, IP_ARGS(&ip), strerror(retval));
-    }
-    return retval;
-}
-
-int
-netdev_arp_lookup(const struct netdev *netdev, uint32_t ip, 
-                  uint8_t mac[ETH_ADDR_LEN]) 
-{
-    return netdev_nodev_arp_lookup(netdev->name, ip, mac);
-}
-
 static int
 get_stats_via_netlink(int ifindex, struct netdev_stats *stats)
 {
diff --git a/lib/netdev.h b/lib/netdev.h
index 9a55619..e876327 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -99,7 +99,6 @@ int netdev_get_flags(const struct netdev *, enum netdev_flags *);
 int netdev_set_flags(struct netdev *, enum netdev_flags, bool permanent);
 int netdev_turn_flags_on(struct netdev *, enum netdev_flags, bool permanent);
 int netdev_turn_flags_off(struct netdev *, enum netdev_flags, bool permanent);
-int netdev_arp_lookup(const struct netdev *, uint32_t ip, uint8_t mac[6]);
 int netdev_get_carrier(const struct netdev *, bool *carrier);
 int netdev_get_stats(const struct netdev *, struct netdev_stats *);
 int netdev_set_policing(struct netdev *, uint32_t kbits_rate, 
@@ -114,8 +113,6 @@ int netdev_nodev_set_etheraddr(const char *name, const uint8_t mac[6]);
 int netdev_nodev_get_etheraddr(const char *netdev_name, uint8_t mac[6]);
 int netdev_nodev_set_policing(const char *netdev_name, uint32_t kbits_rate, 
                               uint32_t kbits_burst);
-int netdev_nodev_arp_lookup(const char *netdev_name, uint32_t ip, 
-                            uint8_t mac[6]);
 int netdev_nodev_get_carrier(const char *netdev_name, bool *carrier);
 
 int netdev_get_vlan_vid(const char *netdev_name, int *vlan_vid);
diff --git a/secchan/in-band.c b/secchan/in-band.c
index 6026efd..881e1fd 100644
--- a/secchan/in-band.c
+++ b/secchan/in-band.c
@@ -22,6 +22,8 @@
 #include <net/if.h>
 #include <string.h>
 #include <stdlib.h>
+#include "dhcp.h"
+#include "dpif.h"
 #include "flow.h"
 #include "mac-learning.h"
 #include "netdev.h"
@@ -30,6 +32,7 @@
 #include "ofproto.h"
 #include "ofpbuf.h"
 #include "openflow/openflow.h"
+#include "openvswitch/datapath-protocol.h"
 #include "packets.h"
 #include "poll-loop.h"
 #include "rconn.h"
@@ -43,15 +46,12 @@
 #define IB_BASE_PRIORITY 18181800
 
 enum {
-    IBR_FROM_LOCAL_PORT,        /* Sent by the local port. */
-    IBR_OFP_TO_LOCAL,           /* Sent to secure channel on local port. */
-    IBR_ARP_FROM_LOCAL,         /* ARP from the local port. */
-    IBR_ARP_TO_LOCAL,           /* ARP to the local port. */
-    IBR_ARP_FROM_CTL,           /* ARP from the controller. */
-    IBR_TO_CTL_OFP_SRC,         /* To controller, OpenFlow source port. */
-    IBR_TO_CTL_OFP_DST,         /* To controller, OpenFlow dest port. */
-    IBR_FROM_CTL_OFP_SRC,       /* From controller, OpenFlow source port. */
-    IBR_FROM_CTL_OFP_DST,       /* From controller, OpenFlow dest port. */
+    IBR_FROM_LOCAL_DHCP,          /* From local port, DHCP. */
+    IBR_TO_LOCAL_DHCP,            /* To local port, DHCP. */
+    IBR_TO_CTL_ARP,               /* To controller, ARP. */
+    IBR_FROM_CTL_ARP,             /* From controller, ARP. */
+    IBR_TO_CTL_OFP,               /* To controller, OpenFlow port. */
+    IBR_FROM_CTL_OFP,             /* From controller, OpenFlow port. */
 #if OFP_TCP_PORT != OFP_SSL_PORT
 #error Need to support separate TCP and SSL flows.
 #endif
@@ -70,17 +70,13 @@ struct in_band {
     struct rconn *controller;
     struct status_category *ss_cat;
 
-    /* Keeping track of controller's MAC address. */
-    uint32_t ip;                /* Current IP, 0 if unknown. */
-    uint32_t last_ip;           /* Last known IP, 0 if never known. */
-    uint8_t mac[ETH_ADDR_LEN];  /* Current MAC, 0 if unknown. */
-    uint8_t last_mac[ETH_ADDR_LEN]; /* Last known MAC, 0 if never known */
-    char *dev_name;
-    time_t next_refresh;        /* Next time to refresh MAC address. */
-
     /* Keeping track of the local port's MAC address. */
-    uint8_t local_mac[ETH_ADDR_LEN]; /* Current MAC. */
-    time_t next_local_refresh;  /* Next time to refresh MAC address. */
+    uint8_t local_mac[ETH_ADDR_LEN];  /* Current MAC. */
+    char local_name[IF_NAMESIZE];  /* Local device name. */
+    time_t next_local_refresh;        /* Next time to refresh MAC address. */
+
+    uint32_t controller_ip;           /* Current IP, 0 if unknown. */
+    time_t next_refresh;
 
     /* Rules that we set up. */
     struct ib_rule rules[N_IB_RULES];
@@ -152,7 +148,7 @@ get_local_mac(struct in_band *ib)
     time_t now = time_now();
     if (now >= ib->next_local_refresh) {
         uint8_t ea[ETH_ADDR_LEN];
-        if (ib->dev_name && (!netdev_nodev_get_etheraddr(ib->dev_name, ea))) {
+        if (!netdev_nodev_get_etheraddr(ib->local_name, ea)) {
             memcpy(ib->local_mac, ea, ETH_ADDR_LEN);
         }
         ib->next_local_refresh = now + 1;
@@ -165,19 +161,12 @@ in_band_status_cb(struct status_reply *sr, void *in_band_)
 {
     struct in_band *in_band = in_band_;
     const uint8_t *local_mac;
-    const uint8_t *controller_mac;
 
     local_mac = get_local_mac(in_band);
     if (local_mac) {
         status_reply_put(sr, "local-mac="ETH_ADDR_FMT,
                          ETH_ADDR_ARGS(local_mac));
     }
-
-    controller_mac = get_controller_mac(in_band);
-    if (controller_mac) {
-        status_reply_put(sr, "controller-mac="ETH_ADDR_FMT,
-                         ETH_ADDR_ARGS(controller_mac));
-    }
 }
 
 static void
@@ -218,103 +207,143 @@ setup_flow(struct in_band *in_band, int rule_idx, const flow_t *flow,
     }
 }
 
+/* Returns true if 'packet' should be sent to the local port regardless
+ * of the flow table. */ 
+bool
+in_band_msg_in_hook(struct in_band *in_band, const flow_t *flow, 
+                    const struct ofpbuf *packet)
+{
+    if (!in_band) {
+        return false;
+    }
+
+    if ((flow->nw_proto == IP_TYPE_UDP)
+            && (flow->tp_src == htons(DHCP_SERVER_PORT))
+            && (flow->tp_dst == htons(DHCP_CLIENT_PORT))
+            && (packet->size >= DHCP_HEADER_LEN)) {
+        struct dhcp_header *dhcp = packet->l7;
+        const uint8_t *local_mac;
+
+        local_mac = get_local_mac(in_band);
+        if (!memcmp(dhcp->chaddr, local_mac, ETH_ADDR_LEN)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/* Returns true if the rule that would match 'flow' with 'actions' is 
+ * allowed to be setup in the datapath. */
+bool
+in_band_rule_check(struct in_band *in_band, const flow_t *flow,
+                   const struct odp_actions *actions)
+{
+    if (!in_band) {
+        return true;
+    }
+
+    /* Don't allow flows that would prevent DHCP replies from being seen
+     * by the local port. */
+    if ((flow->nw_proto == IP_TYPE_UDP)
+            && (flow->tp_src == htons(DHCP_SERVER_PORT)) 
+            && (flow->tp_dst == htons(DHCP_CLIENT_PORT))) {
+        int i;
+
+        for (i=0; i<actions->n_actions; i++) {
+            if (actions->actions[i].output.type == ODPAT_OUTPUT 
+                    && actions->actions[i].output.port == ODPP_LOCAL) {
+                return true;
+            }   
+        }
+        return false;
+    }
+
+    return true;
+}
+
 void
 in_band_run(struct in_band *in_band)
 {
-    const uint8_t *controller_mac;
-    const uint8_t *local_mac;
+    time_t now = time_now();
+    uint32_t controller_ip;
     flow_t flow;
 
-    if (time_now() < MIN(in_band->next_refresh, in_band->next_local_refresh)) {
+    if (now < MIN(in_band->next_refresh, in_band->next_local_refresh)) {
         return;
     }
- 
-    /* NOTE: A router may sit between the switch and controller, so
-     * we could not tie this to the controller's MAC address.  If the
-     * switch and controller are on different subnets, we should be
-     * using the router's MAC address in the 'controller_mac'. */
-    controller_mac = get_controller_mac(in_band);
-    local_mac = get_local_mac(in_band);
 
-    /* Switch traffic sent by the local port. */
-    memset(&flow, 0, sizeof flow);
-    flow.in_port = ODPP_LOCAL;
-    setup_flow(in_band, IBR_FROM_LOCAL_PORT, &flow, OFPFW_IN_PORT,
-               OFPP_NORMAL);
+    controller_ip = rconn_get_remote_ip(in_band->controller);
+    in_band->next_refresh = now + (controller_ip ? 10 : 1);
 
-    if (local_mac) {
-        /* Deliver traffic sent over the secure channel to the connection's
-         * interface. */
-        memset(&flow, 0, sizeof flow);
-        flow.dl_type = htons(ETH_TYPE_IP);
-        memcpy(flow.dl_dst, local_mac, ETH_ADDR_LEN);
-        flow.nw_proto = IP_TYPE_TCP;
-        flow.tp_src = htons(OFP_TCP_PORT);
-        setup_flow(in_band, IBR_OFP_TO_LOCAL, &flow, 
-                    (OFPFW_DL_TYPE | OFPFW_DL_DST | OFPFW_NW_PROTO 
-                     | OFPFW_TP_SRC), OFPP_NORMAL);
-
-        /* Allow the connection's interface to be the source of ARP traffic. */
-        memset(&flow, 0, sizeof flow);
-        flow.dl_type = htons(ETH_TYPE_ARP);
-        memcpy(flow.dl_src, local_mac, ETH_ADDR_LEN);
-        setup_flow(in_band, IBR_ARP_FROM_LOCAL, &flow,
-                   OFPFW_DL_TYPE | OFPFW_DL_SRC, OFPP_NORMAL);
-
-        /* Allow the connection's interface to receive directed ARP traffic. */
-        memset(&flow, 0, sizeof flow);
-        flow.dl_type = htons(ETH_TYPE_ARP);
-        memcpy(flow.dl_dst, local_mac, ETH_ADDR_LEN);
-        setup_flow(in_band, IBR_ARP_TO_LOCAL, &flow, 
-                   OFPFW_DL_TYPE | OFPFW_DL_DST, OFPP_NORMAL);
-    } else {
-        drop_flow(in_band, IBR_OFP_TO_LOCAL);
-        drop_flow(in_band, IBR_ARP_FROM_LOCAL);
-        drop_flow(in_band, IBR_ARP_TO_LOCAL);
+    if (controller_ip == in_band->controller_ip) {
+        return;
+    } else if (!controller_ip) {
+        drop_flow(in_band, IBR_TO_CTL_ARP);
+        drop_flow(in_band, IBR_FROM_CTL_ARP);
+        drop_flow(in_band, IBR_TO_CTL_OFP);
+        drop_flow(in_band, IBR_FROM_CTL_OFP);
+
+        in_band->next_refresh = now + 1;
+        in_band->controller_ip = controller_ip;
+
+        return;
     }
 
-    if (controller_mac) {
-        /* Switch ARP requests sent by the controller.  (OFPP_NORMAL will "do
-         * the right thing" regarding VLANs here.) */
-        memset(&flow, 0, sizeof flow);
-        flow.dl_type = htons(ETH_TYPE_ARP);
-        memcpy(flow.dl_dst, eth_addr_broadcast, ETH_ADDR_LEN);
-        memcpy(flow.dl_src, controller_mac, ETH_ADDR_LEN);
-        setup_flow(in_band, IBR_ARP_FROM_CTL, &flow,
-                   OFPFW_DL_TYPE | OFPFW_DL_DST | OFPFW_DL_SRC,
-                   OFPP_NORMAL);
-
-        /* OpenFlow traffic to or from the controller.
-         *
-         * (A given field's value is completely ignored if it is wildcarded,
-         * which is why we can get away with using a single 'flow' in each
-         * case here.) */
-        memset(&flow, 0, sizeof flow);
-        flow.dl_type = htons(ETH_TYPE_IP);
-        memcpy(flow.dl_src, controller_mac, ETH_ADDR_LEN);
-        memcpy(flow.dl_dst, controller_mac, ETH_ADDR_LEN);
-        flow.nw_proto = IP_TYPE_TCP;
-        flow.tp_src = htons(OFP_TCP_PORT);
-        flow.tp_dst = htons(OFP_TCP_PORT);
-        setup_flow(in_band, IBR_TO_CTL_OFP_SRC, &flow,
-                   (OFPFW_DL_TYPE | OFPFW_DL_DST | OFPFW_NW_PROTO
-                    | OFPFW_TP_SRC), OFPP_NORMAL);
-        setup_flow(in_band, IBR_TO_CTL_OFP_DST, &flow,
-                   (OFPFW_DL_TYPE | OFPFW_DL_DST | OFPFW_NW_PROTO
-                    | OFPFW_TP_DST), OFPP_NORMAL);
-        setup_flow(in_band, IBR_FROM_CTL_OFP_SRC, &flow,
-                   (OFPFW_DL_TYPE | OFPFW_DL_SRC | OFPFW_NW_PROTO
-                    | OFPFW_TP_SRC), OFPP_NORMAL);
-        setup_flow(in_band, IBR_FROM_CTL_OFP_DST, &flow,
-                   (OFPFW_DL_TYPE | OFPFW_DL_SRC | OFPFW_NW_PROTO
-                    | OFPFW_TP_DST), OFPP_NORMAL);
-    } else {
-        drop_flow(in_band, IBR_ARP_FROM_CTL);
-        drop_flow(in_band, IBR_TO_CTL_OFP_DST);
-        drop_flow(in_band, IBR_TO_CTL_OFP_SRC);
-        drop_flow(in_band, IBR_FROM_CTL_OFP_DST);
-        drop_flow(in_band, IBR_FROM_CTL_OFP_SRC);
+    if (in_band->controller_ip) {
+        VLOG_DBG("controller IP address changed from "IP_FMT" to "IP_FMT, 
+                 IP_ARGS(&in_band->controller_ip),
+                 IP_ARGS(&controller_ip));
     }
+    in_band->controller_ip = controller_ip;
+
+    /* Allow DHCP requests to be sent from the local port. */
+    memset(&flow, 0, sizeof flow);
+    flow.in_port = ODPP_LOCAL;
+    flow.dl_type = htons(ETH_TYPE_IP);
+    flow.nw_proto = IP_TYPE_UDP;
+    flow.tp_src = htons(DHCP_CLIENT_PORT);
+    flow.tp_dst = htons(DHCP_SERVER_PORT);
+    setup_flow(in_band, IBR_FROM_LOCAL_DHCP, &flow,
+               (OFPFW_IN_PORT | OFPFW_DL_TYPE | OFPFW_NW_PROTO 
+                | OFPFW_TP_SRC | OFPFW_TP_DST), OFPP_NORMAL);
+
+    /* Allow ARP requests about the controller through. */
+    memset(&flow, 0, sizeof flow);
+    flow.dl_type = htons(ETH_TYPE_ARP);
+    flow.nw_proto = ARP_OP_REQUEST;
+    flow.nw_src = controller_ip;
+    setup_flow(in_band, IBR_TO_CTL_ARP, &flow,
+               (OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK), 
+               OFPP_NORMAL);
+
+    /* Allow ARP requests from the controller through. */
+    memset(&flow, 0, sizeof flow);
+    flow.dl_type = htons(ETH_TYPE_ARP);
+    flow.nw_proto = ARP_OP_REPLY;
+    flow.nw_dst = controller_ip;
+    setup_flow(in_band, IBR_FROM_CTL_ARP, &flow,
+               (OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_DST_MASK), 
+               OFPP_NORMAL);
+ 
+    /* OpenFlow traffic to or from the controller.
+     *
+     * (A given field's value is completely ignored if it is wildcarded,
+     * which is why we can get away with using a single 'flow' in each
+     * case here.) */
+    memset(&flow, 0, sizeof flow);
+    flow.dl_type = htons(ETH_TYPE_IP);
+    flow.nw_proto = IP_TYPE_TCP;
+    flow.nw_src = controller_ip;
+    flow.nw_dst = controller_ip;
+    flow.tp_src = htons(OFP_TCP_PORT);
+    flow.tp_dst = htons(OFP_TCP_PORT);
+    setup_flow(in_band, IBR_FROM_CTL_OFP, &flow,
+               (OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK
+                | OFPFW_TP_SRC), OFPP_NORMAL);
+    setup_flow(in_band, IBR_TO_CTL_OFP, &flow,
+               (OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_DST_MASK 
+                | OFPFW_TP_DST), OFPP_NORMAL);
 }
 
 void
@@ -340,19 +369,27 @@ in_band_flushed(struct in_band *in_band)
 }
 
 void
-in_band_create(struct ofproto *ofproto, struct switch_status *ss,
-               struct rconn *controller, struct in_band **in_bandp)
+in_band_create(struct ofproto *ofproto, struct dpif *dpif,
+               struct switch_status *ss, struct rconn *controller, 
+               struct in_band **in_bandp)
 {
     struct in_band *in_band;
+    int error;
 
     in_band = xcalloc(1, sizeof *in_band);
+    error = dpif_port_get_name(dpif, ODPP_LOCAL, in_band->local_name, 
+                               sizeof in_band->local_name);
+    if (error) {
+        free(in_band);
+        return;
+    }
+
     in_band->ofproto = ofproto;
     in_band->controller = controller;
     in_band->ss_cat = switch_status_register(ss, "in-band",
                                              in_band_status_cb, in_band);
     in_band->next_refresh = TIME_MIN;
     in_band->next_local_refresh = TIME_MIN;
-    in_band->dev_name = NULL;
 
     *in_bandp = in_band;
 }
diff --git a/secchan/in-band.h b/secchan/in-band.h
index 1e13a6a..736ad76 100644
--- a/secchan/in-band.h
+++ b/secchan/in-band.h
@@ -21,16 +21,21 @@
 
 struct dpif;
 struct in_band;
+struct odp_actions;
 struct ofproto;
 struct rconn;
 struct secchan;
 struct settings;
 struct switch_status;
 
-void in_band_create(struct ofproto *, struct switch_status *,
+void in_band_create(struct ofproto *, struct dpif *, struct switch_status *,
                     struct rconn *controller, struct in_band **);
 void in_band_destroy(struct in_band *);
 void in_band_run(struct in_band *);
+bool in_band_msg_in_hook(struct in_band *, const flow_t *, 
+                         const struct ofpbuf *packet);
+bool in_band_rule_check(struct in_band *, const flow_t *,
+                        const struct odp_actions *);
 void in_band_wait(struct in_band *);
 void in_band_flushed(struct in_band *);
 
diff --git a/secchan/ofproto.c b/secchan/ofproto.c
index ad1aa44..acbd83b 100644
--- a/secchan/ofproto.c
+++ b/secchan/ofproto.c
@@ -433,8 +433,8 @@ ofproto_set_in_band(struct ofproto *p, bool in_band)
 {
     if (in_band != (p->in_band != NULL)) {
         if (in_band) {
-            in_band_create(p, p->switch_status, p->controller->rconn, 
-                           &p->in_band);
+            in_band_create(p, &p->dpif, p->switch_status, 
+                           p->controller->rconn, &p->in_band);
             return 0;
         } else {
             ofproto_set_discovery(p, false, NULL, true);
@@ -2105,6 +2105,10 @@ xlate_actions(const union ofp_action *in, size_t n_in,
     ctx.tags = tags ? tags : &no_tags;
     ctx.may_setup_flow = true;
     do_xlate_actions(in, n_in, &ctx);
+    if (!in_band_rule_check(ofproto->in_band, flow, out)) {
+        printf("xxx in_band_rule_check returned false\n");
+        ctx.may_setup_flow = false;
+    }
     if (may_setup_flow) {
         *may_setup_flow = ctx.may_setup_flow;
     }
@@ -2997,6 +3001,21 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet)
     struct ofpbuf payload;
     flow_t flow;
 
+    payload.data = msg + 1;
+    payload.size = msg->length - sizeof *msg;
+    flow_extract(&payload, msg->port, &flow);
+
+    /* Check with in-band control to see if this packet should be sent
+     * to the local port regardless of the flow table. */
+    if (in_band_msg_in_hook(p->in_band, &flow, &payload)) {
+        union odp_action action;
+
+        memset(&action, 0, sizeof(action));
+        action.output.type = ODPAT_OUTPUT;
+        action.output.port = ODPP_LOCAL;
+        dpif_execute(&p->dpif, flow.in_port, &action, 1, &payload);
+    }
+
     /* Handle controller actions. */
     if (msg->type == _ODPL_ACTION_NR) {
         COVERAGE_INC(ofproto_ctlr_action);
@@ -3005,10 +3024,6 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet)
         return;
     }
 
-    payload.data = msg + 1;
-    payload.size = msg->length - sizeof *msg;
-    flow_extract(&payload, msg->port, &flow);
-
     rule = lookup_valid_rule(p, &flow);
     if (!rule) {
         /* Don't send a packet-in if OFPPC_NO_PACKET_IN asserted. */
-- 
1.6.3.1





More information about the discuss mailing list