[ovs-dev] [PATCH 3/4] ovn: Add flows to forward the dhcp traffic to, ovn-controller

Numan Siddique nusiddiq at redhat.com
Fri Oct 23 08:41:08 UTC 2015


A new table is created for controller flows. A logical flow is created
for every datapath, to submit the packets matching DHCP pattern to
the controller table.

An entry is created in the controller table by the ovn-controller to do a
packet-in on every port's MAC address that matches it's chasis id.

Signed-off-by: Numan Siddique <nusiddiq at redhat.com>
---
  ovn/controller/lflow.c        |  1 +
  ovn/controller/lflow.h        |  1 +
  ovn/controller/ofcontroller.c | 33 +++++++++++++++++++++++++++++++++
  ovn/controller/ofcontroller.h |  8 +++++---
  ovn/controller/physical.c     | 12 ++++++++++++
  ovn/lib/actions.c             | 17 +++++++++++------
  ovn/lib/actions.h             |  8 ++++----
  ovn/northd/ovn-northd.c       |  6 ++++++
  ovn/ovn-sb.xml                |  7 +++++++
  tests/test-ovn.c              |  2 +-
  10 files changed, 81 insertions(+), 14 deletions(-)

diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index 38c72c1..49bf44a 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -300,6 +300,7 @@ lflow_run(struct controller_ctx *ctx, struct hmap 
*flow_table,
          error = actions_parse_string(lflow->actions, &symtab, &ldp->ports,
                                       ct_zones, first_ptable, 
LOG_PIPELINE_LEN,
                                       lflow->table_id, output_ptable,
+                                     (uint8_t) OFTABLE_CONTROLLER,
                                       &ofpacts, &prereqs);
          if (error) {
              static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h
index 4a4fa83..b39dd80 100644
--- a/ovn/controller/lflow.h
+++ b/ovn/controller/lflow.h
@@ -49,6 +49,7 @@ struct uuid;
  #define OFTABLE_REMOTE_OUTPUT        32
  #define OFTABLE_LOCAL_OUTPUT         33
  #define OFTABLE_DROP_LOOPBACK        34
+#define OFTABLE_CONTROLLER           35
  #define OFTABLE_LOG_EGRESS_PIPELINE  48 /* First of LOG_PIPELINE_LEN 
tables. */
  #define OFTABLE_LOG_TO_PHY           64

diff --git a/ovn/controller/ofcontroller.c b/ovn/controller/ofcontroller.c
index 8a6c124..8567925 100644
--- a/ovn/controller/ofcontroller.c
+++ b/ovn/controller/ofcontroller.c
@@ -229,3 +229,36 @@ ofcontroller_wait(void)
      }
      pvconn_wait(pvconn);
  }
+
+/*
+ * Add flows to forward the packets to the ovn-controller
+ * for the port in the OFTABLE_CONTROLLER table.
+ */
+void
+ofcontroller_add_flows(const struct sbrec_port_binding *binding,
+                       struct hmap *flow_table)
+{
+    struct match match;
+    struct ofpbuf ofpacts;
+    struct eth_addr mac;
+    ovs_be32 ipv4;
+
+    ofpbuf_init(&ofpacts, 0);
+    for (size_t i = 0; i < binding->n_mac; i++) {
+        if (!ovs_scan(binding->mac[i], ETH_ADDR_SCAN_FMT " " IP_SCAN_FMT,
+                      ETH_ADDR_SCAN_ARGS(mac), IP_SCAN_ARGS(&ipv4))) {
+            continue;
+        }
+        match_init_catchall(&match);
+        ofpbuf_clear(&ofpacts);
+        match_set_metadata(&match, htonll(binding->datapath->tunnel_key));
+        match_set_dl_src(&match, mac);
+        struct ofpact_controller *controller = 
ofpact_put_CONTROLLER(&ofpacts);
+
+        controller->max_len = UINT16_MAX;
+        controller->controller_id = 0;
+        controller->reason = OFPR_ACTION;
+
+        ofctrl_add_flow(flow_table, OFTABLE_CONTROLLER, 50, &match, 
&ofpacts);
+    }
+}
diff --git a/ovn/controller/ofcontroller.h b/ovn/controller/ofcontroller.h
index ea2d7de..05c90f4 100644
--- a/ovn/controller/ofcontroller.h
+++ b/ovn/controller/ofcontroller.h
@@ -26,8 +26,10 @@ void ofcontroller_run(struct controller_ctx *,
  void ofcontroller_wait(void);
  void ofcontroller_destroy(void);

-/*
- * Get the Openflow protocol supported by the client
- */
+/* Get the Openflow protocol supported by the client. */
  enum ofputil_protocol ofcontroller_ofp_proto(void);
+
+/* Add flows to forward the packets to the ovn-controller. */
+void ofcontroller_add_flows(const struct sbrec_port_binding *,
+                            struct hmap *flow_table);
  #endif /* netdev.h */
diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c
index 5821c11..dfa226d 100644
--- a/ovn/controller/physical.c
+++ b/ovn/controller/physical.c
@@ -28,6 +28,7 @@
  #include "smap.h"
  #include "sset.h"
  #include "vswitch-idl.h"
+#include "ofcontroller.h"

  VLOG_DEFINE_THIS_MODULE(physical);

@@ -493,6 +494,17 @@ physical_run(struct controller_ctx *ctx, enum 
mf_field_id mff_ovn_geneve,
          match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, 
binding->tunnel_key);
          ofctrl_add_flow(flow_table, OFTABLE_DROP_LOOPBACK, 100,
                          &match, &ofpacts);
+
+        /* Table 35, Priority 50.
+         * =====================
+         * Add the flows to forward packets to the controller
+         * if the port is bound to this_chassis_id.
+         */
+        if (binding->chassis && binding->chassis->name &&
+            (!strcmp(binding->chassis->name, this_chassis_id))) {
+            ofcontroller_add_flows(binding, flow_table);
+        }
+
      }

      /* Handle output to multicast groups, in tables 32 and 33. */
diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
index ccf97f0..c118c38 100644
--- a/ovn/lib/actions.c
+++ b/ovn/lib/actions.c
@@ -42,6 +42,7 @@ struct action_context {
      uint8_t first_ptable;       /* First OpenFlow table. */
      uint8_t cur_ltable;         /* 0 <= cur_ltable < n_tables. */
      uint8_t output_ptable;      /* OpenFlow table for 'output' to 
resubmit. */
+    uint8_t controller_ptable;  /* OpenFlow table for 'controller' to 
resubmit */
      const struct simap *ct_zones; /* Map from port name to conntrack 
zone. */

  /* State. */
@@ -260,6 +261,8 @@ parse_actions(struct action_context *ctx)
              emit_ct(ctx, true, false);
          } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
              emit_ct(ctx, false, true);
+        } else if (lexer_match_id(ctx->lexer, "controller")) {
+            emit_resubmit(ctx, ctx->controller_ptable);
          } else {
              action_syntax_error(ctx, "expecting action");
          }
@@ -320,7 +323,8 @@ char * OVS_WARN_UNUSED_RESULT
  actions_parse(struct lexer *lexer, const struct shash *symtab,
                const struct simap *ports, const struct simap *ct_zones,
                uint8_t first_ptable, uint8_t n_tables, uint8_t cur_ltable,
-              uint8_t output_ptable, struct ofpbuf *ofpacts,
+              uint8_t output_ptable, uint8_t controller_ptable,
+          struct ofpbuf *ofpacts,
                struct expr **prereqsp)
  {
      size_t ofpacts_start = ofpacts->size;
@@ -334,6 +338,7 @@ actions_parse(struct lexer *lexer, const struct 
shash *symtab,
      ctx.n_tables = n_tables;
      ctx.cur_ltable = cur_ltable;
      ctx.output_ptable = output_ptable;
+    ctx.controller_ptable = controller_ptable;
      ctx.error = NULL;
      ctx.ofpacts = ofpacts;
      ctx.prereqs = NULL;
@@ -356,17 +361,17 @@ char * OVS_WARN_UNUSED_RESULT
  actions_parse_string(const char *s, const struct shash *symtab,
                       const struct simap *ports, const struct simap 
*ct_zones,
                       uint8_t first_table, uint8_t n_tables, uint8_t 
cur_table,
-                     uint8_t output_table, struct ofpbuf *ofpacts,
-                     struct expr **prereqsp)
+                     uint8_t output_table, uint8_t controller_ptable,
+                     struct ofpbuf *ofpacts, struct expr **prereqsp)
  {
      struct lexer lexer;
      char *error;

      lexer_init(&lexer, s);
      lexer_get(&lexer);
-    error = actions_parse(&lexer, symtab, ports, ct_zones, first_table,
-                          n_tables, cur_table, output_table, ofpacts,
-                          prereqsp);
+    error = actions_parse(&lexer, symtab, ports, ct_zones,
+                          first_table, n_tables, cur_table, output_table,
+                          controller_ptable, ofpacts, prereqsp);
      lexer_destroy(&lexer);

      return error;
diff --git a/ovn/lib/actions.h b/ovn/lib/actions.h
index 92f71de..4445b43 100644
--- a/ovn/lib/actions.h
+++ b/ovn/lib/actions.h
@@ -29,15 +29,15 @@ struct simap;
  char *actions_parse(struct lexer *, const struct shash *symtab,
                      const struct simap *ports, const struct simap 
*ct_zones,
                      uint8_t first_ptable, uint8_t n_tables, uint8_t 
cur_ltable,
-                    uint8_t output_ptable, struct ofpbuf *ofpacts,
-                    struct expr **prereqsp)
+                    uint8_t output_ptable, uint8_t controller_ptable,
+                    struct ofpbuf *ofpacts, struct expr **prereqsp)
      OVS_WARN_UNUSED_RESULT;
  char *actions_parse_string(const char *s, const struct shash *symtab,
                             const struct simap *ports,
                             const struct simap *ct_zones, uint8_t 
first_ptable,
                             uint8_t n_tables, uint8_t cur_ltable,
-                           uint8_t output_ptable, struct ofpbuf *ofpacts,
-                           struct expr **prereqsp)
+                           uint8_t output_ptable, uint8_t 
controller_ptable,
+                           struct ofpbuf *ofpacts, struct expr **prereqsp)
      OVS_WARN_UNUSED_RESULT;

  #endif /* ovn/actions.h */
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 60786d2..0d17257 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1167,6 +1167,12 @@ build_lswitch_flows(struct hmap *datapaths, 
struct hmap *ports,
              continue;
          }

+        /* Submit the dhcp packets to the controller table */
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 150,
+                      "ip4 && ip4.src == 0.0.0.0 &&"
+                      "ip4.dst == 255.255.255.255 &&"
+                      " udp && udp.src == 68 && udp.dst == 67",
+                      "controller;");
          ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 100, "eth.mcast",
                        "outport = \""MC_FLOOD"\"; output;");
      }
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index 9c2d411..13d8380 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -906,6 +906,13 @@
            Commit the flow to the connection tracking entry associated
            with it by a previous call to <code>ct_next</code>.
          </dd>
+
+        <dt><code>controller;</code></dt>
+        <dd>
+          Executes controller table as a subroutine. This action will 
be used
+          if the packet needs to be handled by the
+          <code>ovn-controller</code>.
+        </dd>
        </dl>

        <p>
diff --git a/tests/test-ovn.c b/tests/test-ovn.c
index 7c1fc13..f523b83 100644
--- a/tests/test-ovn.c
+++ b/tests/test-ovn.c
@@ -1227,7 +1227,7 @@ test_parse_actions(struct ovs_cmdl_context *ctx 
OVS_UNUSED)

          ofpbuf_init(&ofpacts, 0);
          error = actions_parse_string(ds_cstr(&input), &symtab, &ports,
-                                     &ct_zones, 16, 16, 10, 64,
+                                     &ct_zones, 16, 16, 10, 64, 35,
                                       &ofpacts, &prereqs);
          if (!error) {
              struct ds output;
-- 
1.9.1




More information about the dev mailing list