On Tue, Jun 5, 2018 at 6:24 PM, <[email protected]> wrote:
> From: Venkata Anil <[email protected]>
>
> External switches should learn the distributed gateway port MAC address
> as they have to forward the packet tagged with tenant vlan network but
> with this MAC as destination MAC address. So router has to send ARP
> reply and gARP for this MAC address through router internal patch ports
> connecting tenant vlan networks.
>
> Signed-off-by: Venkata Anil <[email protected]>
> ---
> ovn/controller/pinctrl.c | 57 ++++++++++++++++++++++++++++++
> +++++++++++++-----
> ovn/northd/ovn-northd.c | 57 ++++++++++++++++++++++++++++++
> ++++++++++++++++++
> tests/ovn.at | 6 +++++
> 3 files changed, 114 insertions(+), 6 deletions(-)
>
> diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c
> index 305f206..222bc1c 100644
> --- a/ovn/controller/pinctrl.c
> +++ b/ovn/controller/pinctrl.c
> @@ -2157,8 +2157,47 @@ get_nat_addresses_and_keys(struct controller_ctx
> *ctx,
> const struct sbrec_chassis *chassis,
> const struct chassis_index *chassis_index,
> struct sset *active_tunnels,
> - struct shash *nat_addresses)
> + struct shash *nat_addresses,
> + struct hmap *local_datapaths)
> {
> + /* When a router has tenant vlan networks, gARP for distributed
> gateway
> + * router port has to be sent through internal tenant vlan network's
> + * localnet port, so that external switches can learn this MAC and
> forward
> + * tenant vlan network traffic with distributed gateway router port
> MAC
> + * as destination MAC address */
> +
> + struct local_datapath *ldp;
> + struct shash router_vlan_ports;
> +
> + shash_init(&router_vlan_ports);
> + HMAP_FOR_EACH (ldp, hmap_node, local_datapaths) {
> + const struct sbrec_port_binding *crp;
> + crp = ldp->chassisredirect_port;
> + /* check if it a router with chassis redirect port,
> + * get corresponding distributed port */
> + if (crp && crp->chassis &&
> + !strcmp(crp->chassis->name, chassis->name)) {
> + const struct sbrec_port_binding *dp = NULL;
> + for (int i = 0; i < ldp->n_peer_dps; i++) {
> + if (!strcmp(ldp->peer_dps[i]->patch->logical_port,
> + smap_get(&crp->options, "distributed-port")))
> {
> + dp = ldp->peer_dps[i]->peer;
> + break;
> + }
> + }
> +
> + /* Save router internal port (patch port on tenant vlan
> network)
> + * along with distributed port. */
> + for (int i = 0; i < ldp->n_peer_dps; i++) {
> + if (strcmp(ldp->peer_dps[i]->patch->logical_port,
> + smap_get(&crp->options, "distributed-port"))) {
> + shash_add(&router_vlan_ports,
> + ldp->peer_dps[i]->peer->logical_port, dp);
> + }
> + }
> + }
> + }
> +
> const char *gw_port;
> SSET_FOR_EACH(gw_port, local_l3gw_ports) {
> const struct sbrec_port_binding *pb;
> @@ -2168,9 +2207,14 @@ get_nat_addresses_and_keys(struct controller_ctx
> *ctx,
> continue;
> }
>
> - if (pb->n_nat_addresses) {
> - for (int i = 0; i < pb->n_nat_addresses; i++) {
> - consider_nat_address(ctx, pb->nat_addresses[i], pb,
> + /* Router internatl ports should send gARP for distributed port
> + * NAT addresses */
> + const struct sbrec_port_binding *dp;
> + dp = shash_find_data(&router_vlan_ports, pb->logical_port);
> + const struct sbrec_port_binding *nat_port = dp ? dp : pb;
> + if (nat_port->n_nat_addresses) {
> + for (int i = 0; i < nat_port->n_nat_addresses; i++) {
> + consider_nat_address(ctx, nat_port->nat_addresses[i], pb,
> nat_address_keys, chassis,
> chassis_index, active_tunnels,
> nat_addresses);
> @@ -2178,7 +2222,7 @@ get_nat_addresses_and_keys(struct controller_ctx
> *ctx,
> } else {
> /* Continue to support options:nat-addresses for version
> * upgrade. */
> - const char *nat_addresses_options = smap_get(&pb->options,
> + const char *nat_addresses_options =
> smap_get(&nat_port->options,
> "nat-addresses");
> if (nat_addresses_options) {
> consider_nat_address(ctx, nat_addresses_options, pb,
> @@ -2188,6 +2232,7 @@ get_nat_addresses_and_keys(struct controller_ctx
> *ctx,
> }
> }
> }
> + shash_destroy(&router_vlan_ports);
> }
>
> static void
> @@ -2217,7 +2262,7 @@ send_garp_run(struct controller_ctx *ctx,
>
> get_nat_addresses_and_keys(ctx, &nat_ip_keys, &local_l3gw_ports,
> chassis, chassis_index, active_tunnels,
> - &nat_addresses);
> + &nat_addresses, local_datapaths);
> /* For deleted ports and deleted nat ips, remove from send_garp_data.
> */
> struct shash_node *iter, *next;
> SHASH_FOR_EACH_SAFE (iter, next, &send_garp_data) {
> diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
> index f68da2b..ace3385 100644
> --- a/ovn/northd/ovn-northd.c
> +++ b/ovn/northd/ovn-northd.c
> @@ -4993,6 +4993,63 @@ build_lrouter_flows(struct hmap *datapaths, struct
> hmap *ports,
> ds_cstr(&match), ds_cstr(&actions));
> }
>
> + /* ARP requests for distributed port IP address but coming from
> router
> + * internal network vlan, should be replied through router
> internal
> + * network vlan ports */
> + if (op->od->l3dgw_port && op == op->od->l3dgw_port
> + && op->od->l3redirect_port) {
> + for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
> + ds_clear(&match);
> + ds_put_format(&match,
> + "flags.rcv_from_vlan == 1 && "
> + "arp.tpa == %s && arp.op == 1 && "
> + "is_chassis_resident(%s)",
> + op->lrp_networks.ipv4_addrs[i].addr_s,
> + op->od->l3redirect_port->json_key);
> +
> + ds_clear(&actions);
> + ds_put_format(&actions,
> + "eth.dst = eth.src; "
> + "eth.src = %s; "
> + "arp.op = 2; /* ARP reply */ "
> + "arp.tha = arp.sha; "
> + "arp.sha = %s; "
> + "arp.tpa = arp.spa; "
> + "arp.spa = %s; "
> + "flags.loopback = 1; ",
> + op->lrp_networks.ea_s,
> + op->lrp_networks.ea_s,
> + op->lrp_networks.ipv4_addrs[i].addr_s);
> +
> + /* Add internal vlan network ports as output ports */
> + bool router_ports_exist = false;
> + struct ovn_datapath *dp;
> + HMAP_FOR_EACH (dp, key_node, datapaths) {
> + if (!dp->nbs) {
> + continue;
> + }
> + if (!dp->localnet_port) {
> + continue;
> + }
> + for (size_t j = 0; j < dp->n_router_ports; j++) {
> + struct ovn_port *rp = dp->router_ports[j];
> + if (rp->peer && rp->peer->od == op->od &&
> + rp->peer != op) {
> + router_ports_exist = true;
> + ds_put_format(&actions,
> + "outport = %s; "
> + "output;",
> + rp->peer->json_key);
> + }
> + }
> + }
> + if (router_ports_exist) {
> + ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT,
> 90,
> + ds_cstr(&match), ds_cstr(&actions));
> + }
>
Hi Anil,
You need to document these flows in ovn-northd.8.xml
Thanks
Numan
> + }
> + }
> +
> /* A set to hold all load-balancer vips that need ARP responses.
> */
> struct sset all_ips = SSET_INITIALIZER(&all_ips);
> int addr_family;
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 7a6993b..b2e7a5c 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -7889,6 +7889,12 @@ foo_mac="000001010203"
> gw_mac="000002010203"
> nexthop_mac="f00000010204"
>
> +# gARP for distributed port has to be sent through router internal patch
> port
> +# which is connected to vlan network
> +garp=ffffffffffff${gw_mac}8100000208060001080006040001${
> gw_mac}${gw_ip}000000000000${gw_ip}
> +echo $garp >> hv1-br-ex_n2-rx.expected
> +OVN_CHECK_PACKETS([hv1/br-ex_n2-rx.pcap], [hv1-br-ex_n2-rx.expected])
> +
> # Send ip packet from foo1 to 8.8.8.8
> src_mac="f00000010203"
> dst_mac="000001010203"
> --
> 1.8.3.1
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev