From a0281b2eab10a2053cd4f143c02bfd8cc8a12f24 Mon Sep 17 00:00:00 2001 From: Hiroki Shirokura Date: Sat, 19 Dec 2020 10:50:18 +0900 Subject: [PATCH] bgpd: cli for srv6-locator assignment (step4) This commit add command to speficy SRv6 locator for BGP SRv6-VPN. CLI example is follow. CLI block of "segment-routing" is already implemented by previous commits and it's managed by zebra. Zebra manage just the ownership of locator's prefix. Zlient can request to get srv6-locator's prefix chunk using srv6_manager_get_locator_chunk() which is usuful func to execute ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK api. This request is wokring as async, And zebra calls same api to Zclients when zebra allocate locator prefix chunk. And then, finally zclient(bgpd) catch the information via process_srv6_lcoator_chunk callback function. router bgp 1 segment-routing srv6 locator loc1 ! ! segment-routing srv6 locators locator loc1 prefix 2001:db8:1:1::/64 ! ! ! ! [POINT_OF_REVIEW] In current implementation, user can just configure srv6 locator but user can't de-configure srv6 locator. Signed-off-by: Hiroki Shirokura --- bgpd/bgp_vty.c | 32 ++++++++++++++++++++++++++ bgpd/bgp_zebra.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_zebra.h | 1 + 3 files changed, 93 insertions(+) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 8067c338849d..a236d4e30c6e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -9870,6 +9870,29 @@ DEFUN_NOSH (bgp_segment_routing_srv6, return CMD_SUCCESS; } +DEFPY (bgp_srv6_locator, + bgp_srv6_locator_cmd, + "locator NAME$name", + "Specify SRv6 locator\n" + "Specify SRv6 locator\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (strlen(bgp->srv6_locator_name) > 0 + && strcmp(name, bgp->srv6_locator_name) != 0) { + vty_out(vty, "srv6 locator is already configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } else + snprintf(bgp->srv6_locator_name, + sizeof(bgp->srv6_locator_name), "%s", name); + + int ret = bgp_zebra_srv6_manager_get_locator_chunk(name); + if (ret < 0) + return CMD_WARNING_CONFIG_FAILED; + + return CMD_SUCCESS; +} + DEFUN_NOSH (exit_address_family, exit_address_family_cmd, "exit-address-family", @@ -17887,6 +17910,14 @@ int bgp_config_write(struct vty *vty) if (CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN)) vty_out(vty, " bgp shutdown\n"); + if (bgp->srv6_enabled) { + vty_frame(vty, " !\n segment-routing srv6\n"); + if (bgp->srv6_locator_name) + vty_out(vty, " locator %s\n", + bgp->srv6_locator_name); + } + + /* IPv4 unicast configuration. */ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST); @@ -19461,6 +19492,7 @@ void bgp_vty_init(void) /* srv6 commands */ install_element(BGP_NODE, &bgp_segment_routing_srv6_cmd); + install_element(BGP_SRV6_NODE, &bgp_srv6_locator_cmd); } #include "memory.h" diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 97f781b2bfa1..c66348691baa 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2976,6 +2976,60 @@ static int bgp_ifp_create(struct interface *ifp) return 0; } +static void bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS) +{ + struct stream *s = NULL; + uint8_t proto; + uint16_t instance; + uint16_t len; + char name[256] = {0}; + struct prefix_ipv6 *chunk = NULL; + chunk = prefix_ipv6_new(); + + s = zclient->ibuf; + STREAM_GETC(s, proto); + STREAM_GETW(s, instance); + + STREAM_GETW(s, len); + STREAM_GET(name, s, len); + + STREAM_GETW(s, chunk->prefixlen); + STREAM_GET(&chunk->prefix, s, 16); + + if (zclient->redist_default != proto) { + zlog_err("Got SRv6 Manager msg with wrong proto %u", proto); + return; + } + if (zclient->instance != instance) { + zlog_err("Got SRv6 Manager msg with wrong instance %u", proto); + return; + } + + struct bgp *bgp = bgp_get_default(); + if (strcmp(bgp->srv6_locator_name, name) != 0) { + zlog_info("name unmatch %s:%s", + bgp->srv6_locator_name, name); + return; + } + + struct listnode *node; + struct prefix_ipv6 *c; + for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, c)) { + if (!prefix_cmp(c, chunk)) + return; + } + + listnode_add(bgp->srv6_locator_chunks, chunk); + vpn_leak_postchange_all(); + return; + +stream_failure: + free(chunk); + + zlog_err("%s: can't get locator_chunk!!", __func__); + return; +} + void bgp_zebra_init(struct thread_master *master, unsigned short instance) { zclient_num_connects = 0; @@ -3018,6 +3072,7 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance) zclient->iptable_notify_owner = iptable_notify_owner; zclient->route_notify_owner = bgp_zebra_route_notify_owner; zclient->instance = instance; + zclient->process_srv6_locator_chunk = bgp_zebra_process_srv6_locator_chunk; } void bgp_zebra_destroy(void) @@ -3415,3 +3470,8 @@ int bgp_zebra_stale_timer_update(struct bgp *bgp) zlog_debug("send capabilty success"); return BGP_GR_SUCCESS; } + +int bgp_zebra_srv6_manager_get_locator_chunk(const char *name) +{ + return srv6_manager_get_locator_chunk(zclient, name); +} diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 4b357c380afc..02b6484943ed 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -113,4 +113,5 @@ extern void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh, extern int bgp_zebra_send_capabilities(struct bgp *bgp, bool disable); extern int bgp_zebra_update(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type); extern int bgp_zebra_stale_timer_update(struct bgp *bgp); +extern int bgp_zebra_srv6_manager_get_locator_chunk(const char *name); #endif /* _QUAGGA_BGP_ZEBRA_H */