This is required by next commit that allows lswitch with localnet
port to be attached to multiple chassises. Without this patch, if
an ARP request comes from localnet port, on each chassis there will
be an ARP response, which is not desired.
An new stage ls_in_arp_rsp is introduced for ARP responder before
ls_in_l2_lkup.
Suggested-by: Russell Bryant <russell@ovn.org>
Signed-off-by: Han Zhou <zhouhan@gmail.com>
Acked-by: Russell Bryant <russell@ovn.org>
Signed-off-by: Ben Pfaff <blp@ovn.org>
- <h3>Ingress Table 3: Destination Lookup</h3>
+ <h3>Ingress Table 3: ARP responder</h3>
- This table implements switching behavior. It contains these logical
- flows:
+ This table implements ARP responder for known IPs. It contains these
+ logical flows:
+ <li>
+ Priority-100 flows to skip ARP responder if inport is of type
+ <code>localnet</code>, and advances directly to table 3.
+ </li>
+
- Priority-150 flows that matches ARP requests to each known IP address
+ Priority-50 flows that matches ARP requests to each known IP address
<var>A</var> of logical port <var>P</var>, and respond with ARP
replies directly with corresponding Ethernet address <var>E</var>:
</p>
<var>A</var> of logical port <var>P</var>, and respond with ARP
replies directly with corresponding Ethernet address <var>E</var>:
</p>
+ <li>
+ One priority-0 fallback flow that matches all packets and advances to
+ table 4.
+ </li>
+ </ul>
+
+ <h3>Ingress Table 4: Destination Lookup</h3>
+
+ <p>
+ This table implements switching behavior. It contains these logical
+ flows:
+ </p>
+
+ <ul>
<li>
A priority-100 flow that outputs all packets with an Ethernet broadcast
or multicast <code>eth.dst</code> to the <code>MC_FLOOD</code>
<li>
A priority-100 flow that outputs all packets with an Ethernet broadcast
or multicast <code>eth.dst</code> to the <code>MC_FLOOD</code>
PIPELINE_STAGE(SWITCH, IN, PORT_SEC, 0, "ls_in_port_sec") \
PIPELINE_STAGE(SWITCH, IN, PRE_ACL, 1, "ls_in_pre_acl") \
PIPELINE_STAGE(SWITCH, IN, ACL, 2, "ls_in_acl") \
PIPELINE_STAGE(SWITCH, IN, PORT_SEC, 0, "ls_in_port_sec") \
PIPELINE_STAGE(SWITCH, IN, PRE_ACL, 1, "ls_in_pre_acl") \
PIPELINE_STAGE(SWITCH, IN, ACL, 2, "ls_in_acl") \
- PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 3, "ls_in_l2_lkup") \
+ PIPELINE_STAGE(SWITCH, IN, ARP_RSP, 3, "ls_in_arp_rsp") \
+ PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 4, "ls_in_l2_lkup") \
\
/* Logical switch egress stages. */ \
PIPELINE_STAGE(SWITCH, OUT, PRE_ACL, 0, "ls_out_pre_acl") \
\
/* Logical switch egress stages. */ \
PIPELINE_STAGE(SWITCH, OUT, PRE_ACL, 0, "ls_out_pre_acl") \
- /* Ingress table 3: Destination lookup, ARP reply for known IPs.
- * (priority 150). */
+ /* Ingress table 3: ARP responder, skip requests coming from localnet ports.
+ * (priority 100). */
+ HMAP_FOR_EACH (op, key_node, ports) {
+ if (!op->nbs) {
+ continue;
+ }
+
+ if (!strcmp(op->nbs->type, "localnet")) {
+ char *match = xasprintf("inport == %s", op->json_key);
+ ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_RSP, 100,
+ match, "next;");
+ free(match);
+ }
+ }
+
+ /* Ingress table 3: ARP responder, reply for known IPs.
+ * (priority 50). */
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbs) {
continue;
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbs) {
continue;
ETH_ADDR_ARGS(laddrs.ea),
ETH_ADDR_ARGS(laddrs.ea),
IP_ARGS(laddrs.ipv4_addrs[j].addr));
ETH_ADDR_ARGS(laddrs.ea),
ETH_ADDR_ARGS(laddrs.ea),
IP_ARGS(laddrs.ipv4_addrs[j].addr));
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_L2_LKUP, 150,
+ ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_RSP, 50,
match, actions);
free(match);
free(actions);
match, actions);
free(match);
free(actions);
- /* Ingress table 3: Destination lookup, broadcast and multicast handling
+ /* Ingress table 3: ARP responder, by default goto next.
+ * (priority 0)*/
+ HMAP_FOR_EACH (od, key_node, datapaths) {
+ if (!od->nbs) {
+ continue;
+ }
+
+ ovn_lflow_add(lflows, od, S_SWITCH_IN_ARP_RSP, 0, "1", "next;");
+ }
+
+ /* Ingress table 4: Destination lookup, broadcast and multicast handling
* (priority 100). */
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbs) {
* (priority 100). */
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbs) {
"outport = \""MC_FLOOD"\"; output;");
}
"outport = \""MC_FLOOD"\"; output;");
}
- /* Ingress table 3: Destination lookup, unicast handling (priority 50), */
+ /* Ingress table 4: Destination lookup, unicast handling (priority 50), */
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbs) {
continue;
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbs) {
continue;
- /* Ingress table 3: Destination lookup for unknown MACs (priority 0). */
+ /* Ingress table 4: Destination lookup for unknown MACs (priority 0). */
HMAP_FOR_EACH (od, key_node, datapaths) {
if (!od->nbs) {
continue;
HMAP_FOR_EACH (od, key_node, datapaths) {
if (!od->nbs) {
continue;