summaryrefslogtreecommitdiff
path: root/ovn
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2015-10-17 14:07:12 -0700
committerBen Pfaff <blp@nicira.com>2015-10-19 08:46:18 -0700
commit86e9804898a6cb373553d36940effead38183cdd (patch)
treec108094c1276dfab4b32b7b50e42651a38ccd686 /ovn
parente3393e3ff8d80269c00da2c16637146feca1d037 (diff)
downloadopenvswitch-86e9804898a6cb373553d36940effead38183cdd.tar.gz
ovn: Support multiple router ports per logical switch.
This allows multiple subnets to be routed directly to a logical switch. Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Justin Pettit <jpettit@nicira.com>
Diffstat (limited to 'ovn')
-rw-r--r--ovn/TODO10
-rw-r--r--ovn/northd/ovn-northd.c69
-rw-r--r--ovn/ovn-nb.xml7
3 files changed, 47 insertions, 39 deletions
diff --git a/ovn/TODO b/ovn/TODO
index 7f695085d..1f2a73f63 100644
--- a/ovn/TODO
+++ b/ovn/TODO
@@ -2,16 +2,6 @@
* L3 support
-** OVN_Northbound schema
-
-*** Needs to support extra routes
-
-Currently a router port has a single route associated with it, but
-presumably we should support multiple routes. For connections from
-one router to another, this doesn't seem to matter (just put more than
-one connection between them), but for connections between a router and
-a switch it might matter because a switch has only one router port.
-
** New OVN logical actions
*** arp
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index e6e9f3e9f..a1ad34c20 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -237,7 +237,8 @@ struct ovn_datapath {
ovs_be32 gateway;
/* Logical switch data. */
- struct ovn_port *router_port;
+ struct ovn_port **router_ports;
+ size_t n_router_ports;
struct hmap port_tnlids;
uint32_t port_key_hint;
@@ -271,6 +272,7 @@ ovn_datapath_destroy(struct hmap *datapaths, struct ovn_datapath *od)
* use it. */
hmap_remove(datapaths, &od->key_node);
destroy_tnlids(&od->port_tnlids);
+ free(od->router_ports);
free(od);
}
}
@@ -634,7 +636,10 @@ join_logical_ports(struct northd_context *ctx,
peer->peer = op;
op->peer = peer;
- op->od->router_port = op;
+ op->od->router_ports = xrealloc(
+ op->od->router_ports,
+ sizeof *op->od->router_ports * (op->od->n_router_ports + 1));
+ op->od->router_ports[op->od->n_router_ports++] = op;
} else if (op->nbr && op->nbr->peer) {
char peer_name[UUID_LEN + 1];
snprintf(peer_name, sizeof peer_name, UUID_FMT,
@@ -1431,18 +1436,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
HMAP_FOR_EACH (op, key_node, ports) {
if (op->nbr) {
/* XXX ARP for neighboring router */
- } else if (op->od->router_port) {
- const char *peer_name = smap_get(
- &op->od->router_port->nbs->options, "router-port");
- if (!peer_name) {
- continue;
- }
-
- struct ovn_port *peer = ovn_port_find(ports, peer_name);
- if (!peer || !peer->nbr) {
- continue;
- }
-
+ } else if (op->od->n_router_ports) {
for (size_t i = 0; i < op->nbs->n_addresses; i++) {
struct eth_addr ea;
ovs_be32 ip;
@@ -1450,18 +1444,41 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
if (ovs_scan(op->nbs->addresses[i],
ETH_ADDR_SCAN_FMT" "IP_SCAN_FMT,
ETH_ADDR_SCAN_ARGS(ea), IP_SCAN_ARGS(&ip))) {
- char *match = xasprintf("reg0 == "IP_FMT, IP_ARGS(ip));
- char *actions = xasprintf("eth.src = "ETH_ADDR_FMT"; "
- "eth.dst = "ETH_ADDR_FMT"; "
- "outport = %s; "
- "output;",
- ETH_ADDR_ARGS(peer->mac),
- ETH_ADDR_ARGS(ea),
- peer->json_key);
- ovn_lflow_add(lflows, peer->od,
- S_ROUTER_IN_ARP, 200, match, actions);
- free(actions);
- free(match);
+ for (size_t j = 0; j < op->od->n_router_ports; j++) {
+ /* Get the Logical_Router_Port that the Logical_Port is
+ * connected to, as 'peer'. */
+ const char *peer_name = smap_get(
+ &op->od->router_ports[j]->nbs->options,
+ "router-port");
+ if (!peer_name) {
+ continue;
+ }
+
+ struct ovn_port *peer
+ = ovn_port_find(ports, peer_name);
+ if (!peer || !peer->nbr) {
+ continue;
+ }
+
+ /* Make sure that 'ip' is in 'peer''s network. */
+ if ((ip ^ peer->network) & peer->mask) {
+ continue;
+ }
+
+ char *match = xasprintf("reg0 == "IP_FMT, IP_ARGS(ip));
+ char *actions = xasprintf("eth.src = "ETH_ADDR_FMT"; "
+ "eth.dst = "ETH_ADDR_FMT"; "
+ "outport = %s; "
+ "output;",
+ ETH_ADDR_ARGS(peer->mac),
+ ETH_ADDR_ARGS(ea),
+ peer->json_key);
+ ovn_lflow_add(lflows, peer->od,
+ S_ROUTER_IN_ARP, 200, match, actions);
+ free(actions);
+ free(match);
+ break;
+ }
}
}
}
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index ae0d8e202..0bfb587fe 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -142,9 +142,10 @@
</p>
<p>
- A given logical switch may have at most one logical port of type
- <code>router</code>. (This is not a significant restriction because
- logical routers may be connected into arbitrary topologies.)
+ If a given logical switch has multiple <code>router</code> ports, the
+ <ref table="Logical_Router_Port"/> rows that they reference must be
+ all on the same <ref table="Logical_Router"/> (for different
+ subnets).
</p>
<column name="options" key="router-port" type='{"type": "uuid"}'>