#undef PIPELINE_STAGE
};
+/* Due to various hard-coded priorities need to implement ACLs, the
+ * northbound database supports a smaller range of ACL priorities than
+ * are available to logical flows. This value is added to an ACL
+ * priority to determine the ACL's logical flow priority. */
+#define OVN_ACL_PRI_OFFSET 1000
+
/* Returns an "enum ovn_stage" built from the arguments. */
static enum ovn_stage
ovn_stage_build(enum ovn_datapath_type dp_type, enum ovn_pipeline pipeline,
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;
* use it. */
hmap_remove(datapaths, &od->key_node);
destroy_tnlids(&od->port_tnlids);
+ free(od->router_ports);
free(od);
}
}
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,
* may and then its return traffic would not have an
* associated conntrack entry and would return "+invalid". */
const char *actions = has_stateful ? "ct_commit; next;" : "next;";
- ovn_lflow_add(lflows, od, stage, acl->priority,
+ ovn_lflow_add(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
acl->match, actions);
} else if (!strcmp(acl->action, "allow-related")) {
struct ds match = DS_EMPTY_INITIALIZER;
* other traffic related to this entry to flow due to the
* 65535 priority flow defined earlier. */
ds_put_format(&match, "ct.new && (%s)", acl->match);
- ovn_lflow_add(lflows, od, stage, acl->priority,
+ ovn_lflow_add(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
ds_cstr(&match), "ct_commit; next;");
ds_destroy(&match);
} else if (!strcmp(acl->action, "drop")) {
- ovn_lflow_add(lflows, od, stage, acl->priority,
+ ovn_lflow_add(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
acl->match, "drop;");
} else if (!strcmp(acl->action, "reject")) {
/* xxx Need to support "reject". */
VLOG_INFO("reject is not a supported action");
- ovn_lflow_add(lflows, od, stage, acl->priority,
+ ovn_lflow_add(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
acl->match, "drop;");
}
}
ETH_ADDR_ARGS(op->mac), op->json_key);
ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ADMISSION, 50,
match, "next;");
+ free(match);
}
/* Logical router ingress table 1: IP Input. */
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;
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;
+ }
}
}
}