> On 10 Aug 2024, at 00:17, Mark Michelson <[email protected]> wrote: > > Martin et al., > > I plan to commit the branch patches and to create the 24.09 branch shortly. > Since we stated intent to get this patch into 24.09, we will work to get it > into main and branch-24.09 as soon as we can next week. > Hi Mark. Thank you for leniency with regards to this patch. I’m putting all my efforts to fixing this.
Martin. > Thanks, > Mark Michelson > > On 8/9/24 14:40, Martin Kalcok wrote: >> This change adds two new LRP options: >> * routing-protocol-redirect >> * routing-protocols >> These allow redirection of a routing protocol traffic to >> an Logical Switch Port. This enables external routing daemons >> to listen on an interface bound to an LSP and effectively act >> as if they were listening on (and speaking from) LRP's IP address. >> Option 'routing-protocols' takes a comma-separated list of routing >> protocols whose traffic should be redirected. Currently supported >> are BGP (tcp 179) and BFD (udp 3784). >> Option 'routing-protocol-redirect' expects a string with an LSP >> name. >> When both of these options are set, any traffic entering LS >> that's destined for LRP's IP addresses (including IPv6 LLA) and >> routing protocol's port number, is redirected to the LSP specified >> in the 'routing-protocol-redirect' value. >> NOTE: this feature is experimental and may be subject to >> removal/change in the future. >> Signed-off-by: Martin Kalcok <[email protected]> >> --- >> I'm posting this v7 patch just as a preview. northd occasionally >> crashes in the added datapath tests. It's an issue I can't seem to >> reproduce in my test deployment, only during the tests. Until that's >> resolved, this patch is not suitable for merging. >> Compared to v6, this patch includes: >> Fix for cloning of ARP/ND messages. Now the messages are >> properly delivered to both, redirect port and the LRP. >> It also adds functional test that verifies ability of hosts on >> internal networks to communicate with the external networks >> uninterupted, even when the worwarding is enabled >> northd/northd.c | 225 ++++++++++++++++++++++++++++++++++++++++ >> northd/northd.h | 7 ++ >> northd/ovn-northd.8.xml | 54 ++++++++++ >> ovn-nb.xml | 42 ++++++++ >> tests/ovn-northd.at | 93 +++++++++++++++++ >> tests/system-ovn.at | 120 +++++++++++++++++++++ >> 6 files changed, 541 insertions(+) >> diff --git a/northd/northd.c b/northd/northd.c >> index 0c73e70df..9f2fd5278 100644 >> --- a/northd/northd.c >> +++ b/northd/northd.c >> @@ -13935,6 +13935,229 @@ build_arp_resolve_flows_for_lrp(struct ovn_port >> *op, >> } >> } >> +static void >> +build_routing_protocols_redirect_rule__( >> + const char *s_addr, const char *redirect_port_name, int >> protocol_port, >> + const char *proto, bool is_ipv6, struct ovn_port *ls_peer, >> + struct lflow_table *lflows, struct ds *match, struct ds *actions) >> +{ >> + int ip_ver = is_ipv6 ? 6 : 4; >> + ds_clear(actions); >> + ds_put_format(actions, "outport = \"%s\"; output;", redirect_port_name); >> + >> + /* Redirect packets in the input pipeline destined for LR's IP >> + * and the routing protocol's port to the LSP specified in >> + * 'routing-protocol-redirect' option.*/ >> + ds_clear(match); >> + ds_put_format(match, "ip%d.dst == %s && %s.dst == %d", ip_ver, s_addr, >> + proto, protocol_port); >> + ovn_lflow_add(lflows, ls_peer->od, S_SWITCH_IN_L2_LKUP, 100, >> + ds_cstr(match), >> + ds_cstr(actions), >> + ls_peer->lflow_ref); >> + >> + /* To accomodate "peer" nature of the routing daemons, redirect also >> + * replies to the daemons' client requests. */ >> + ds_clear(match); >> + ds_put_format(match, "ip%d.dst == %s && %s.src == %d", ip_ver, s_addr, >> + proto, protocol_port); >> + ovn_lflow_add(lflows, ls_peer->od, S_SWITCH_IN_L2_LKUP, 100, >> + ds_cstr(match), >> + ds_cstr(actions), >> + ls_peer->lflow_ref); >> +} >> + >> +static void >> +apply_routing_protocols_redirect__( >> + const char *s_addr, const char *redirect_port_name, int >> protocol_flags, >> + bool is_ipv6, struct ovn_port *ls_peer, struct lflow_table *lflows, >> + struct ds *match, struct ds *actions) >> +{ >> + if (protocol_flags & REDIRECT_BGP) { >> + build_routing_protocols_redirect_rule__(s_addr, redirect_port_name, >> + 179, "tcp", is_ipv6, >> ls_peer, >> + lflows, match, actions); >> + } >> + >> + if (protocol_flags & REDIRECT_BFD) { >> + build_routing_protocols_redirect_rule__(s_addr, redirect_port_name, >> + 3784, "udp", is_ipv6, >> ls_peer, >> + lflows, match, actions); >> + } >> + >> + /* Because the redirected port shares IP and MAC addresses with the LRP, >> + * special consideration needs to be given to the signaling protocols. >> */ >> + if (is_ipv6) { >> + /* Ensure that redirect port receives copy of NA messages destined >> to >> + * its IP.*/ >> + ds_clear(match); >> + ds_clear(actions); >> + ds_put_format(actions, >> + "clone { outport = \"%s\"; output; }; " >> + "outport = %s; output;", >> + redirect_port_name, ls_peer->json_key); >> + ds_put_format(match, "ip6.dst == %s && nd_na", s_addr); >> + ovn_lflow_add(lflows, ls_peer->od, S_SWITCH_IN_L2_LKUP, 100, >> + ds_cstr(match), >> + ds_cstr(actions), >> + ls_peer->lflow_ref); >> + } else { >> + /* Ensure that redirect port receives copy of ARP replies destined >> to >> + * its IP */ >> + ds_clear(match); >> + ds_clear(actions); >> + ds_put_format(actions, >> + "clone { outport = \"%s\"; output; }; " >> + "outport = %s; output;", >> + redirect_port_name, ls_peer->json_key); >> + ds_put_format(match, "arp.op == 2 && arp.tpa == %s", s_addr); >> + ovn_lflow_add(lflows, ls_peer->od, S_SWITCH_IN_L2_LKUP, 100, >> + ds_cstr(match), >> + ds_cstr(actions), >> + ls_peer->lflow_ref); >> + } >> +} >> + >> +static int >> +parse_redirected_routing_protocols(struct ovn_port *lrp) { >> + int redirected_protocol_flags = 0; >> + const char *redirect_protocols = smap_get(&lrp->nbrp->options, >> + "routing-protocols"); >> + if (redirect_protocols == NULL) { >> + return redirected_protocol_flags; >> + } >> + >> + char *proto; >> + char *save_ptr = NULL; >> + char *tokstr = xstrdup(redirect_protocols); >> + for (proto = strtok_r(tokstr, ",", &save_ptr); proto != NULL; >> + proto = strtok_r(NULL, ",", &save_ptr)) { >> + if (!strcmp(proto, "BGP")) { >> + redirected_protocol_flags |= REDIRECT_BGP; >> + continue; >> + } >> + >> + if (!strcmp(proto, "BFD")) { >> + redirected_protocol_flags |= REDIRECT_BFD; >> + continue; >> + } >> + >> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); >> + VLOG_WARN_RL(&rl, "Option 'routing-protocols' encountered unknown " >> + "value %s", >> + proto); >> + } >> + free(tokstr); >> + return redirected_protocol_flags; >> +} >> + >> +static void >> +build_lrouter_routing_protocol_redirect( >> + struct ovn_port *op, struct lflow_table *lflows, >> + struct ds *match, struct ds *actions) >> +{ >> + /* LRP has to have a peer.*/ >> + if (op->peer == NULL) { >> + return; >> + } >> + >> + /* LRP has to have NB record.*/ >> + if (op->nbrp == NULL) { >> + return; >> + } >> + >> + /* Proceed only for LRPs that have 'routing-protocol-redirect' option >> set. >> + * Value of this option is the name of LSP to which the routing protocol >> + * traffic will be redirected. */ >> + const char *redirect_port = smap_get(&op->nbrp->options, >> + "routing-protocol-redirect"); >> + if (redirect_port == NULL) { >> + return; >> + } >> + >> + if (op->cr_port != NULL) { >> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); >> + VLOG_WARN_RL(&rl, "Option 'routing-protocol-redirect' is not " >> + "supported on Distributed Gateway Port '%s'", >> + op->key); >> + return; >> + } >> + >> + /* Ensure that LSP, to which the routing protocol traffic is redirected, >> + * exists. */ >> + struct ovn_port *peer_lsp; >> + bool redirect_port_exists = false; >> + HMAP_FOR_EACH (peer_lsp, dp_node, &op->peer->od->ports) { >> + size_t peer_lsp_s = strlen(peer_lsp->key); >> + if (peer_lsp_s == strlen(redirect_port) >> + && !strncmp(peer_lsp->key, redirect_port, peer_lsp_s)){ >> + redirect_port_exists = true; >> + break; >> + } >> + } >> + >> + if (!redirect_port_exists) { >> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); >> + VLOG_WARN_RL(&rl, "Option 'routing-protocol-redirect' set on >> Logical " >> + "Router Port '%s' refers to non-existent Logical " >> + "Switch Port. Routing protocol redirecting won't >> be " >> + "configured.", >> + op->key); >> + return; >> + } >> + >> + int redirected_protocols = parse_redirected_routing_protocols(op); >> + if (!redirected_protocols) { >> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); >> + VLOG_WARN_RL(&rl, "Option 'routing-protocol-redirect' is set on " >> + "Logical Router Port '%s' but no known protocols " >> + "were set via 'routing-protocols' options. This " >> + "configuration has no effect.", >> + op->key); >> + return; >> + } >> + >> + /* Redirected traffic destined for LRP's IPs and the specified routing >> + * protocol ports to the port defined in 'routing-protocol-redirect' >> + * option.*/ >> + for (size_t i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) { >> + const char *ip_s = op->lrp_networks.ipv4_addrs[i].addr_s; >> + apply_routing_protocols_redirect__(ip_s, redirect_port, >> + redirected_protocols, false, >> + op->peer, lflows,match, actions); >> + } >> + for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) { >> + const char *ip_s = op->lrp_networks.ipv6_addrs[i].addr_s; >> + apply_routing_protocols_redirect__(ip_s, redirect_port, >> + redirected_protocols, true, >> + op->peer, lflows,match, actions); >> + } >> + >> + /* Drop ARP replies and IPv6 RA/NA packets originating from >> + * 'routing-protocol-redirect' LSP. As this port shares IP and MAC >> + * addresses with LRP, we don't want to create duplicates.*/ >> + ds_clear(match); >> + ds_put_format(match, "inport == \"%s\" && arp.op == 2", redirect_port); >> + ovn_lflow_add(lflows, op->peer->od, S_SWITCH_IN_CHECK_PORT_SEC, 80, >> + ds_cstr(match), >> + REGBIT_PORT_SEC_DROP " = 1; next;", >> + op->peer->lflow_ref); >> + >> + ds_clear(match); >> + ds_put_format(match, "inport == \"%s\" && nd_na", redirect_port); >> + ovn_lflow_add(lflows, op->peer->od, S_SWITCH_IN_CHECK_PORT_SEC, 80, >> + ds_cstr(match), >> + REGBIT_PORT_SEC_DROP " = 1; next;", >> + op->peer->lflow_ref); >> + >> + ds_clear(match); >> + ds_put_format(match, "inport == \"%s\" && nd_ra", redirect_port); >> + ovn_lflow_add(lflows, op->peer->od, S_SWITCH_IN_CHECK_PORT_SEC, 80, >> + ds_cstr(match), >> + REGBIT_PORT_SEC_DROP " = 1; next;", >> + op->peer->lflow_ref); >> +} >> + >> /* This function adds ARP resolve flows related to a LSP. */ >> static void >> build_arp_resolve_flows_for_lsp( >> @@ -16900,6 +17123,8 @@ build_lswitch_and_lrouter_iterate_by_lrp(struct >> ovn_port *op, >> op->lflow_ref); >> build_lrouter_icmp_packet_toobig_admin_flows(op, lsi->lflows, >> &lsi->match, >> &lsi->actions, >> op->lflow_ref); >> + build_lrouter_routing_protocol_redirect(op, lsi->lflows, >> + &lsi->match, &lsi->actions); >> } >> static void * >> diff --git a/northd/northd.h b/northd/northd.h >> index e04ec5856..9e326b746 100644 >> --- a/northd/northd.h >> +++ b/northd/northd.h >> @@ -93,6 +93,13 @@ ovn_datapath_find_by_key(struct hmap *datapaths, uint32_t >> dp_key); >> bool od_has_lb_vip(const struct ovn_datapath *od); >> +/* List of routing and routing-related protocols which >> + * OVN is capable of redirecting from LRP to specific LSP. */ >> +enum redirected_routing_protcol_flag_type { >> + REDIRECT_BGP = (1 << 0), >> + REDIRECT_BFD = (1 << 1), >> +}; >> + >> struct tracked_ovn_ports { >> /* tracked created ports. >> * hmapx node data is 'struct ovn_port *' */ >> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml >> index 3abd5f75b..ede38882a 100644 >> --- a/northd/ovn-northd.8.xml >> +++ b/northd/ovn-northd.8.xml >> @@ -284,6 +284,32 @@ >> dropped in the next stage. >> </li> >> + <li> >> + <p> >> + For each logical port that's defined as a target of routing >> protocol >> + redirecting (via <code>routing-protocol-redirect</code> option >> set on >> + Logical Router Port), a filter is set in place that disallows >> + following traffic exiting this port: >> + </p> >> + <ul> >> + <li> >> + ARP replies >> + </li> >> + <li> >> + IPv6 Neighbor Discovery - Router Advertisements >> + </li> >> + <li> >> + IPv6 Neighbor Discovery - Neighbor Advertisements >> + </li> >> + </ul> >> + <p> >> + Since this port shares IP and MAC addresses with the Logical >> Router >> + Port, we wan't to prevent duplicate replies and advertisements. >> This >> + is achieved by a rule with priority 80 that sets >> + <code>REGBIT_PORT_SEC_DROP" = 1; next;"</code>. >> + </p> >> + </li> >> + >> <li> >> For each (enabled) vtep logical port, a priority 70 flow is added >> which >> matches on all packets and applies the action >> @@ -2002,6 +2028,34 @@ output; >> on the logical switch. >> </li> >> + <li> >> + <p> >> + For any logical port that's defined as a target of routing >> protocol >> + redirecting (via <code>routing-protocol-redirect</code> option >> set on >> + Logical Router Port), we redirect the traffic related to protocols >> + specified in <code>routing-protocols</code> option. It's >> acoomplished >> + with following priority-100 flows: >> + </p> >> + <ul> >> + <li> >> + Flows that match Logical Router Port's IPs and destination port >> of >> + the routing daemon are redirected to this port to allow external >> + peers' connection to the daemon listening on this port. >> + </li> >> + <li> >> + Flows that match Logical Router Port's IPs and source port of >> + the routing daemon are redirected to this port to allow replies >> + from the peers. >> + </li> >> + </ul> >> + <p> >> + In addition to this, we add priority-100 rules that >> + <code>clone</code> ARP replies and IPv6 Neighbor Advertisements to >> + this port as well. These allow to build proper ARP/IPv6 neighbor >> + list on this port. >> + </p> >> + </li> >> + >> <li> >> Priority-90 flows for transit switches that forward registered >> IP multicast traffic to their corresponding multicast group , which >> diff --git a/ovn-nb.xml b/ovn-nb.xml >> index bbda423a5..2836f58f5 100644 >> --- a/ovn-nb.xml >> +++ b/ovn-nb.xml >> @@ -3575,6 +3575,48 @@ or >> </p> >> </column> >> + <column name="options" key="routing-protocol-redirect" >> + type='{"type": "string"}'> >> + <p> >> + NOTE: this feature is experimental and may be subject to >> + removal/change in the future. >> + </p> >> + <p> >> + This option expects a name of a Logical Switch Port that's present >> + in the peer's Logical Switch. If set, it causes any traffic >> + that's destined for Logical Router Port's IP addresses (including >> + its IPv6 LLA) and the ports associated with routing protocols >> defined >> + ip <code>routing-protocols</code> option, to be redirected >> + to the specified Logical Switch Port. >> + >> + This allows external routing daemons to be bound to a port in >> OVN's >> + Logical Switch and act as if they were listening on Logical Router >> + Port's IP addresses. >> + </p> >> + </column> >> + >> + <column name="options" key="routing-protocols" type='{"type": >> "string"}'> >> + <p> >> + NOTE: this feature is experimental and may be subject to >> + removal/change in the future. >> + </p> >> + <p> >> + This option expects a comma-separated list of routing, and >> + routing-related protocols, whose control plane traffic will be >> + redirected to a port specified in >> + <code>routing-protocol-redirect</code> option. Currently supported >> + options are: >> + </p> >> + <ul> >> + <li> >> + <code>BGP</code> (forwards TCP port 179) >> + </li> >> + <li> >> + <code>BFD</code> (forwards UDP port 3784) >> + </li> >> + </ul> >> + </column> >> + >> <column name="options" key="gateway_mtu_bypass"> >> <p> >> When configured, represents a match expression, in the same >> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at >> index f2f42275a..bd05da3cd 100644 >> --- a/tests/ovn-northd.at >> +++ b/tests/ovn-northd.at >> @@ -13757,3 +13757,96 @@ AT_CHECK([grep -e "172.168.0.110" -e >> "172.168.0.120" -e "10.0.0.3" -e "20.0.0.3" >> AT_CLEANUP >> ]) >> + >> +OVN_FOR_EACH_NORTHD_NO_HV([ >> +AT_SETUP([Routing protocol control plane redirect]) >> +ovn_start >> + >> +check ovn-sbctl chassis-add hv1 geneve 127.0.0.1 >> + >> +check ovn-nbctl lr-add lr -- \ >> + lrp-add lr lr-ls 02:ac:10:01:00:01 172.16.1.1/24 >> +check ovn-nbctl --wait=sb set logical_router lr options:chassis=hv1 >> + >> +check ovn-nbctl ls-add ls -- \ >> + lsp-add ls ls-lr -- \ >> + lsp-set-type ls-lr router -- \ >> + lsp-set-addresses ls-lr router -- \ >> + lsp-set-options ls-lr router-port=lr-ls >> + >> +check ovn-nbctl lsp-add ls lsp-bgp -- \ >> + lsp-set-addresses lsp-bgp unknown >> + >> +# Function that ensures that no redirect rules are installed. >> +check_no_redirect() { >> + AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep -E >> "tcp.dst == 179|tcp.src == 179" | wc -l], [0], [0 >> +]) >> + >> + AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_check_port_sec | grep -E >> "priority=80" | wc -l], [0], [0 >> +]) >> + check_no_bfd_redirect >> +} >> + >> +# Function that ensures that no BFD redirect rules are installed. >> +check_no_bfd_redirect() { >> + AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep -E >> "udp.dst == 3784|udp.src == 3784" | wc -l], [0], [0 >> +]) >> +} >> + >> +# By default, no rules related to routing protocol redirect are present >> +check_no_redirect >> + >> +# Set "lsp-bgp" port as target of BGP control plane redirected traffic >> +check ovn-nbctl --wait=sb set logical_router_port lr-ls >> options:routing-protocol-redirect=lsp-bgp >> +check ovn-nbctl --wait=sb set logical_router_port lr-ls >> options:routing-protocols=BGP >> + >> +# Check that BGP control plane traffic is redirected "lsp-bgp" >> +AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep -E "tcp.dst >> == 179|tcp.src == 179" | ovn_strip_lflows], [0], [dnl >> + table=??(ls_in_l2_lkup ), priority=100 , match=(ip4.dst == >> 172.16.1.1 && tcp.dst == 179), action=(outport = "lsp-bgp"; output;) >> + table=??(ls_in_l2_lkup ), priority=100 , match=(ip4.dst == >> 172.16.1.1 && tcp.src == 179), action=(outport = "lsp-bgp"; output;) >> + table=??(ls_in_l2_lkup ), priority=100 , match=(ip6.dst == >> fe80::ac:10ff:fe01:1 && tcp.dst == 179), action=(outport = "lsp-bgp"; >> output;) >> + table=??(ls_in_l2_lkup ), priority=100 , match=(ip6.dst == >> fe80::ac:10ff:fe01:1 && tcp.src == 179), action=(outport = "lsp-bgp"; >> output;) >> +]) >> + >> +# Check that ARP/ND traffic is cloned to the "lsp-bgp" >> +AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep "arp.op == 2 >> && arp.tpa == 172.16.1.1" | ovn_strip_lflows], [0], [dnl >> + table=??(ls_in_l2_lkup ), priority=100 , match=(arp.op == 2 && >> arp.tpa == 172.16.1.1), action=(clone { outport = "lsp-bgp"; output; }; >> outport = "ls-lr"; output;) >> +]) >> +AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep "&& nd_na" | >> ovn_strip_lflows], [0], [dnl >> + table=??(ls_in_l2_lkup ), priority=100 , match=(ip6.dst == >> fe80::ac:10ff:fe01:1 && nd_na), action=(clone { outport = "lsp-bgp"; output; >> }; outport = "ls-lr"; output;) >> +]) >> + >> +# Check that at this point no BFD redirecting is present >> +check_no_bfd_redirect >> + >> +# Add BFD traffic redirect >> +check ovn-nbctl --wait=sb set logical_router_port lr-ls >> options:routing-protocols=BGP,BFD >> + >> +# Check that BFD traffic is redirected to "lsp-bgp" >> +AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep -E "udp.dst >> == 3784|udp.src == 3784" | ovn_strip_lflows], [0], [dnl >> + table=??(ls_in_l2_lkup ), priority=100 , match=(ip4.dst == >> 172.16.1.1 && udp.dst == 3784), action=(outport = "lsp-bgp"; output;) >> + table=??(ls_in_l2_lkup ), priority=100 , match=(ip4.dst == >> 172.16.1.1 && udp.src == 3784), action=(outport = "lsp-bgp"; output;) >> + table=??(ls_in_l2_lkup ), priority=100 , match=(ip6.dst == >> fe80::ac:10ff:fe01:1 && udp.dst == 3784), action=(outport = "lsp-bgp"; >> output;) >> + table=??(ls_in_l2_lkup ), priority=100 , match=(ip6.dst == >> fe80::ac:10ff:fe01:1 && udp.src == 3784), action=(outport = "lsp-bgp"; >> output;) >> +]) >> + >> + >> +# Check that ARP replies and ND advertisements are blocked from exiting >> "lsp-bgp" >> +AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_check_port_sec | grep >> "priority=80" | ovn_strip_lflows], [0], [dnl >> + table=??(ls_in_check_port_sec), priority=80 , match=(inport == >> "lsp-bgp" && arp.op == 2), action=(reg0[[15]] = 1; next;) >> + table=??(ls_in_check_port_sec), priority=80 , match=(inport == >> "lsp-bgp" && nd_na), action=(reg0[[15]] = 1; next;) >> + table=??(ls_in_check_port_sec), priority=80 , match=(inport == >> "lsp-bgp" && nd_ra), action=(reg0[[15]] = 1; next;) >> +]) >> + >> +# Remove 'bgp-redirect' option from LRP and check that rules are removed >> +check ovn-nbctl --wait=sb remove logical_router_port lr-ls options >> routing-protocol-redirect >> +check ovn-nbctl --wait=sb remove logical_router_port lr-ls options >> routing-protocols >> +check_no_redirect >> + >> +# Set non-existent LSP as target of 'bgp-redirect' and check that no rules >> are added >> +check ovn-nbctl --wait=sb set logical_router_port lr-ls >> options:routing-protocol-redirect=lsp-foo >> +check ovn-nbctl --wait=sb set logical_router_port lr-ls >> options:routing-protocols=BGP,BFD >> +check_no_redirect >> + >> +AT_CLEANUP >> +]) >> diff --git a/tests/system-ovn.at b/tests/system-ovn.at >> index 7ba2e150b..c0adb8cc2 100644 >> --- a/tests/system-ovn.at >> +++ b/tests/system-ovn.at >> @@ -13504,3 +13504,123 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port >> patch-.*/d >> AT_CLEANUP >> ]) >> + >> +OVN_FOR_EACH_NORTHD([ >> +AT_SETUP([Routing protocol redirect]) >> +AT_SKIP_IF([test $HAVE_NC = no]) >> + >> +ovn_start >> +OVS_TRAFFIC_VSWITCHD_START() >> + >> +ADD_BR([br-int]) >> +ADD_BR([br-ext]) >> + >> +check ovs-ofctl add-flow br-ext action=normal >> +# Set external-ids in br-int needed for ovn-controller >> +check ovs-vsctl \ >> + -- set Open_vSwitch . external-ids:system-id=hv1 \ >> + -- set Open_vSwitch . >> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ >> + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ >> + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ >> + -- set bridge br-int fail-mode=secure >> other-config:disable-in-band=true >> + >> +# Start ovn-controller >> +start_daemon ovn-controller >> + >> +check ovn-nbctl lr-add R1 \ >> + -- set Logical_Router R1 options:chassis=hv1 >> + >> +check ovn-nbctl ls-add public >> +check ovn-nbctl ls-add bar >> + >> +check ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24 >> +check ovn-nbctl lrp-add R1 rp-bar 00:00:ff:00:00:01 192.168.10.1/24 >> + >> +check ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port >> public-rp \ >> + type=router options:router-port=rp-public \ >> + -- lsp-set-addresses public-rp router >> + >> +check ovn-nbctl lsp-add bar bar-rp -- set Logical_Switch_Port bar-rp \ >> + type=router options:router-port=rp-bar \ >> + -- lsp-set-addresses bar-rp router >> + >> +check ovn-nbctl lsp-add public bgp-daemon \ >> + -- lsp-set-addresses bgp-daemon unknown >> + >> +# Setup container "bar1" representing host on an internal network >> +ADD_NAMESPACES(bar1) >> +ADD_VETH(bar1, bar1, br-int, "192.168.10.2/24", "00:00:ff:ff:ff:01", \ >> + "192.168.10.1") >> +check ovn-nbctl lsp-add bar bar1 \ >> + -- lsp-set-addresses bar1 "00:00:ff:ff:ff:01 192.168.10.2" >> + >> +# Setup SNAT for the internal host >> +AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.10.2]) >> + >> +# Configure external connectivity >> +AT_CHECK([ovs-vsctl set Open_vSwitch . >> external-ids:ovn-bridge-mappings=phynet:br-ext]) >> +check ovn-nbctl lsp-add public public1 \ >> + -- lsp-set-addresses public1 unknown \ >> + -- lsp-set-type public1 localnet \ >> + -- lsp-set-options public1 network_name=phynet >> + >> +check ovn-nbctl --wait=hv sync >> + >> +# Set option that redirects BGP traffic to a LSP "bgp-daemon" >> +check ovn-nbctl --wait=sb set logical_router_port rp-public >> options:routing-protocol-redirect=bgp-daemon >> +check ovn-nbctl --wait=sb set logical_router_port rp-public >> options:routing-protocols=BGP >> + >> +# Create "bgp-daemon" interface in a namespace with IP and MAC matching LRP >> "rp-public" >> +ADD_NAMESPACES(bgp-daemon) >> +ADD_VETH(bgp-daemon, bgp-daemon, br-int, "172.16.1.1/24", >> "00:00:02:01:02:03") >> + >> +ADD_NAMESPACES(ext-foo) >> +ADD_VETH(ext-foo, ext-foo, br-ext, "172.16.1.100/24", "00:10:10:01:02:13", \ >> + "172.16.1.1") >> + >> +# Flip the interface down/up to get proper IPv6 LLA >> +NS_EXEC([bgp-daemon], [ip link set down bgp-daemon]) >> +NS_EXEC([bgp-daemon], [ip link set up bgp-daemon]) >> +NS_EXEC([ext-foo], [ip link set down ext-foo]) >> +NS_EXEC([ext-foo], [ip link set up ext-foo]) >> + >> +# Wait until IPv6 LLA loses the "tentative" flag otherwise it can't be >> bound to. >> +OVS_WAIT_UNTIL([NS_EXEC([bgp-daemon], [ip a show dev bgp-daemon | grep >> "fe80::" | grep -v tentative])]) >> +OVS_WAIT_UNTIL([NS_EXEC([ext-foo], [ip a show dev ext-foo | grep "fe80::" | >> grep -v tentative])]) >> + >> +# Verify that BGP control plane traffic is delivered to the "bgp-daemon" >> +# interface on both IPv4 and IPv6 LLA addresses >> +NETNS_DAEMONIZE([bgp-daemon], [nc -l -k 172.16.1.1 179], [bgp_v4.pid]) >> +NS_CHECK_EXEC([ext-foo], [echo "TCP test" | nc --send-only 172.16.1.1 179]) >> + >> +NETNS_DAEMONIZE([bgp-daemon], [nc -l -6 -k >> fe80::200:2ff:fe01:203%bgp-daemon 179], [bgp_v6.pid]) >> +NS_CHECK_EXEC([ext-foo], [echo "TCP test" | nc --send-only -6 >> fe80::200:2ff:fe01:203%ext-foo 179]) >> + >> +# Verify connection in other direction. i.e when daemon running on >> "bgp-daemon" port >> +# makes a client connection to its peer >> +NETNS_DAEMONIZE([ext-foo], [nc -l -k 172.16.1.100 179], [reply_bgp_v4.pid]) >> +NS_CHECK_EXEC([bgp-daemon], [echo "TCP test" | nc --send-only 172.16.1.100 >> 179]) >> + >> +NETNS_DAEMONIZE([ext-foo], [nc -l -6 -k fe80::210:10ff:fe01:213%ext-foo >> 179], [reply_bgp_v6.pid]) >> +NS_CHECK_EXEC([bgp-daemon], [echo "TCP test" | nc --send-only -6 >> fe80::210:10ff:fe01:213%bgp-daemon 179]) >> + >> +# Verify that hosts on the internal network can reach external networks >> +NETNS_DAEMONIZE([ext-foo], [nc -l -k 172.16.1.100 2222], [nc_external.pid]) >> +NS_CHECK_EXEC([bar1], [echo "TCP test" | nc -w 1 --send-only 172.16.1.100 >> 2222]) >> + >> +OVS_APP_EXIT_AND_WAIT([ovn-controller]) >> + >> +as ovn-sb >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) >> + >> +as ovn-nb >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) >> + >> +as northd >> +OVS_APP_EXIT_AND_WAIT([ovn-northd]) >> + >> +as >> +OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d >> +/.*terminating with signal 15.*/d"]) >> +AT_CLEANUP >> +]) > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
