@@ -21,6 +21,7 @@
#include "lflow.h"
#include "lport.h"
#include "chassis.h"
+#include "pinctrl.h"
#include "lib/bundle.h"
#include "openvswitch/poll-loop.h"
#include "lib/uuid.h"
@@ -235,8 +236,14 @@ get_zone_ids(const struct sbrec_port_binding *binding,
}
static void
-put_replace_router_port_mac_flows(const struct sbrec_port_binding *localnet_port,
+put_replace_router_port_mac_flows(struct ovsdb_idl_index
+ *sbrec_chassis_by_name,
+ struct ovsdb_idl_index
+ *sbrec_port_binding_by_name,
+ const struct sbrec_port_binding
+ *localnet_port,
const struct sbrec_chassis *chassis,
+ const struct sset *active_tunnels,
const struct hmap *local_datapaths,
struct ofpbuf *ofpacts_p,
ofp_port_t ofport,
@@ -277,8 +284,22 @@ put_replace_router_port_mac_flows(const struct sbrec_port_binding *localnet_port
char *err_str = NULL;
struct match match;
struct ofpact_mac *replace_mac;
+ char *cr_peer_name = xasprintf("cr-%s", rport_binding->logical_port);
- /* Table 65, priority 150.
+
+ if (pinctrl_is_chassis_resident(sbrec_chassis_by_name,
+ sbrec_port_binding_by_name,
+ chassis, active_tunnels,
+ cr_peer_name)) {
+ /* If a router port's chassisredirect port is resident on this chassis,
+ * then we need not do mac replace. */
+ free(cr_peer_name);
+ continue;
+ }
+
+ free(cr_peer_name);
+
+ /* Table 65, priority 150.
* =======================
*
* Implements output to localnet port.
@@ -793,7 +814,10 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_chassis_by_name,
&match, ofpacts_p);
if (!strcmp(binding->type, "localnet")) {
- put_replace_router_port_mac_flows(binding, chassis, local_datapaths,
+ put_replace_router_port_mac_flows(sbrec_chassis_by_name,
+ sbrec_port_binding_by_name,
+ binding, chassis,
+ active_tunnels, local_datapaths,
ofpacts_p, ofport, flow_table);
}
@@ -67,13 +67,6 @@ static void destroy_buffered_packets_map(void);
static void pinctrl_handle_put_mac_binding(const struct flow *md,
const struct flow *headers,
bool is_arp);
-static bool
-pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name,
- struct ovsdb_idl_index *sbrec_port_binding_by_name,
- const struct sbrec_chassis *chassis,
- const struct sset *active_tunnels,
- const char *port_name);
-
static void init_put_mac_bindings(void);
static void destroy_put_mac_bindings(void);
static void run_put_mac_bindings(
@@ -134,6 +127,31 @@ pinctrl_init(void)
init_buffered_packets_map();
}
+bool
+pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name,
+ struct ovsdb_idl_index *sbrec_port_binding_by_name,
+ const struct sbrec_chassis *chassis,
+ const struct sset *active_tunnels,
+ const char *port_name)
+{
+ const struct sbrec_port_binding *pb
+ = lport_lookup_by_name(sbrec_port_binding_by_name, port_name);
+ if (!pb || !pb->chassis) {
+ return false;
+ }
+ if (strcmp(pb->type, "chassisredirect")) {
+ return pb->chassis == chassis;
+ } else {
+ struct ovs_list *gateway_chassis =
+ gateway_chassis_get_ordered(sbrec_chassis_by_name, pb);
+ bool active = gateway_chassis_is_active(gateway_chassis,
+ chassis,
+ active_tunnels);
+ gateway_chassis_destroy(gateway_chassis);
+ return active;
+ }
+}
+
static ovs_be32
queue_msg(struct ofpbuf *msg)
{
@@ -2405,31 +2423,6 @@ get_localnet_vifs_l3gwports(
sbrec_port_binding_index_destroy_row(target);
}
-static bool
-pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name,
- struct ovsdb_idl_index *sbrec_port_binding_by_name,
- const struct sbrec_chassis *chassis,
- const struct sset *active_tunnels,
- const char *port_name)
-{
- const struct sbrec_port_binding *pb
- = lport_lookup_by_name(sbrec_port_binding_by_name, port_name);
- if (!pb || !pb->chassis) {
- return false;
- }
- if (strcmp(pb->type, "chassisredirect")) {
- return pb->chassis == chassis;
- } else {
- struct ovs_list *gateway_chassis =
- gateway_chassis_get_ordered(sbrec_chassis_by_name, pb);
- bool active = gateway_chassis_is_active(gateway_chassis,
- chassis,
- active_tunnels);
- gateway_chassis_destroy(gateway_chassis);
- return active;
- }
-}
-
/* Extracts the mac, IPv4 and IPv6 addresses, and logical port from
* 'addresses' which should be of the format 'MAC [IP1 IP2 ..]
* [is_chassis_resident("LPORT_NAME")]', where IPn should be a valid IPv4
@@ -45,4 +45,10 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn);
void pinctrl_destroy(void);
+bool
+pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name,
+ struct ovsdb_idl_index *sbrec_port_binding_by_name,
+ const struct sbrec_chassis *chassis,
+ const struct sset *active_tunnels,
+ const char *port_name);
#endif /* ovn/pinctrl.h */
@@ -12282,7 +12282,7 @@ ovn-nbctl list logical_router_port
AT_CLEANUP
-AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis mac])
+AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR E-W chassis mac])
ovn_start
@@ -12292,6 +12292,8 @@ ovn_start
# of VIF port name indicates the hypervisor it is bound to, e.g.
# lp23 means VIF 3 on hv2.
#
+# Both the switches are connected to a logical router "router".
+#
# Each switch's VLAN tag and their logical switch ports are:
# - ls1:
# - tagged with VLAN 101
@@ -12475,6 +12477,105 @@ as hv2 ovs-appctl fdb/show br-phys
OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected])
+
+# Associate a chassis as gateway chassis and validate garp.
+
+OVN_CLEANUP([hv1],[hv2])
+
+AT_CLEANUP
+
+
+AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR N-S GARP])
+ovn_start
+
+
+# In this test cases we create 2 switches, all connected to same
+# physical network (through br-phys on each HV). Each switch has
+# 1 VIF. Each HV has 1 VIF port. The first digit
+# of VIF port name indicates the hypervisor it is bound to, e.g.
+# lp23 means VIF 3 on hv2.
+#
+# Both the switches are connected to a logical router "router".
+#
+# Additionally, we create a logical switch (ls-underlay) for N-S traffic.
+#
+# Each switch's VLAN tag and their logical switch ports are:
+# - ls1:
+# - tagged with VLAN 101
+# - ports: lp11
+# - ls2:
+# - tagged with VLAN 201
+# - ports: lp22
+# - ls-underlay:
+# - tagged with VLAN 1000
+#
+# Note: a localnet port is created for each switch to connect to
+# physical network.
+# lsp_to_ls LSP
+#
+# Prints the name of the logical switch that contains LSP.
+
+net_add n1
+for i in 1 2; do
+ sim_add hv$i
+ as hv$i
+ ovs-vsctl add-br br-phys
+ ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
+ ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i"
+ ovs-vsctl set open . external-ids:system-id="HV$i"
+ ovn_attach n1 br-phys 192.168.0.$i
+ ovs-vsctl set-controller br-int ptcp:
+done
+
+ovn-nbctl ls-add ls-underlay vlan
+ovn-nbctl lsp-add ls-underlay ln3 "" 1000
+ovn-nbctl lsp-set-addresses ln3 unknown
+ovn-nbctl lsp-set-type ln3 localnet
+ovn-nbctl lsp-set-options ln3 network_name=phys
+
+ovn-nbctl lr-add router
+ovn-nbctl lrp-add router router-to-underlay 00:00:01:01:02:07 172.31.0.1/24
+
+ovn-nbctl lsp-add ls-underlay underlay-to-router -- set Logical_Switch_Port \
+ underlay-to-router type=router \
+ options:router-port=router-to-underlay \
+ -- lsp-set-addresses underlay-to-router router
+
+ovn-nbctl --wait=sb sync
+
+# Associate hv2 as gateway chassis
+ovn-nbctl lrp-set-gateway-chassis router-to-underlay hv2
+
+ovn-nbctl show
+ovn-sbctl show
+
+# Dump a bunch of info helpful for debugging if there's a failure.
+
+echo "------ OVN dump ------"
+ovn-nbctl show
+ovn-sbctl show
+
+echo "------ hv1 dump ------"
+as hv1 ovs-vsctl show
+as hv1 ovs-vsctl list Open_Vswitch
+
+echo "------ hv2 dump ------"
+as hv2 ovs-vsctl show
+as hv2 ovs-vsctl list Open_Vswitch
+
+sleep 1
+
+echo "----------- Post Traffic hv1 dump -----------"
+as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
+as hv1 ovs-appctl fdb/show br-phys
+
+echo "----------- Post Traffic hv2 dump -----------"
+as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
+as hv2 ovs-appctl fdb/show br-phys
+
+AT_CHECK([as hv2 ovs-appctl fdb/show br-phys | grep 00:00:01:01:02:07 | grep 1000 | wc -l], [0], [[1
+]])
+
OVN_CLEANUP([hv1],[hv2])
AT_CLEANUP
Background: [1] https://mail.openvswitch.org/pipermail/ovs-dev/2018-October/353066.html [2] https://docs.google.com/document/d/1uoQH478wM1OZ16HrxzbOUvk5LvFnfNEWbkPT6Zmm9OU/edit?usp=sharing This Series: Layer 2, Layer 3 E-W and Layer 3 N-S (NO NAT) changes for vlan backed distributed logical router. This Patch: a. Do not replace router port mac, if the corrsponding cr- port is resident on current chassis. b. We do not need this, as gateway chassis is where we will advertise the router port mac. Signed-off-by: Ankur Sharma <ankur.sharma@nutanix.com> --- ovn/controller/physical.c | 30 ++++++++++++-- ovn/controller/pinctrl.c | 57 +++++++++++-------------- ovn/controller/pinctrl.h | 6 +++ tests/ovn.at | 103 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 160 insertions(+), 36 deletions(-)