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 <nusid...@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
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev