From 2ee0effb5e2636cba0b27671c20f50cdfa4d7d09 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Tue, 10 Mar 2020 18:20:49 -0700 Subject: [PATCH 1/5] lib: vrf northbound callbacks Signed-off-by: Chirag Shah --- lib/vrf.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++ lib/vrf.h | 2 + lib/yang.c | 1 + yang/frr-vrf.yang | 53 ++++++----------- 4 files changed, 167 insertions(+), 34 deletions(-) diff --git a/lib/vrf.c b/lib/vrf.c index 370a1b235ae0..9346771b05e1 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -36,6 +36,7 @@ #include "privs.h" #include "nexthop_group.h" #include "lib_errors.h" +#include "northbound.h" /* default VRF ID value used when VRF backend is not NETNS */ #define VRF_DEFAULT_INTERNAL 0 @@ -1010,3 +1011,147 @@ vrf_id_t vrf_generate_id(void) return ++vrf_id_local; } + +/* ------- Northbound callbacks ------- */ + +/* + * XPath: /frr-vrf:lib/vrf + */ +static int lib_vrf_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + const char *vrfname; + struct vrf *vrfp; + + vrfname = yang_dnode_get_string(dnode, "./name"); + + if (event != NB_EV_APPLY) + return NB_OK; + + vrfp = vrf_get(VRF_UNKNOWN, vrfname); + + nb_running_set_entry(dnode, vrfp); + + return NB_OK; +} + +static int lib_vrf_destroy(enum nb_event event, const struct lyd_node *dnode) +{ + struct vrf *vrfp; + + + switch (event) { + case NB_EV_VALIDATE: + vrfp = nb_running_get_entry(dnode, NULL, true); + if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) { + zlog_debug("%s Only inactive VRFs can be deleted", + __func__); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrfp = nb_running_unset_entry(dnode); + /* Clear configured flag and invoke delete. */ + UNSET_FLAG(vrfp->status, VRF_CONFIGURED); + vrf_delete(vrfp); + break; + } + + return NB_OK; +} + +static const void *lib_vrf_get_next(const void *parent_list_entry, + const void *list_entry) +{ + struct vrf *vrfp = (struct vrf *)list_entry; + + if (list_entry == NULL) { + vrfp = RB_MIN(vrf_name_head, &vrfs_by_name); + } else { + vrfp = RB_NEXT(vrf_name_head, vrfp); + } + + return vrfp; +} + +static int lib_vrf_get_keys(const void *list_entry, struct yang_list_keys *keys) +{ + struct vrf *vrfp = (struct vrf *)list_entry; + + keys->num = 1; + strlcpy(keys->key[0], vrfp->name, sizeof(keys->key[0])); + + return NB_OK; +} + +static const void *lib_vrf_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys) +{ + const char *vrfname = keys->key[0]; + + struct vrf *vrf = vrf_lookup_by_name(vrfname); + + return vrf; +} + +/* + * XPath: /frr-vrf:lib/vrf/id + */ +static struct yang_data *lib_vrf_state_id_get_elem(const char *xpath, + const void *list_entry) +{ + struct vrf *vrfp = (struct vrf *)list_entry; + + return yang_data_new_uint32(xpath, vrfp->vrf_id); +} + +/* + * XPath: /frr-vrf:lib/vrf/active + */ +static struct yang_data *lib_vrf_state_active_get_elem(const char *xpath, + const void *list_entry) +{ + struct vrf *vrfp = (struct vrf *)list_entry; + + if (vrfp->status == VRF_ACTIVE) + return yang_data_new_bool( + xpath, vrfp->status == VRF_ACTIVE ? true : false); + + return NULL; +} + +/* clang-format off */ +const struct frr_yang_module_info frr_vrf_info = { + .name = "frr-vrf", + .nodes = { + { + .xpath = "/frr-vrf:lib/vrf", + .cbs = { + .create = lib_vrf_create, + .destroy = lib_vrf_destroy, + .get_next = lib_vrf_get_next, + .get_keys = lib_vrf_get_keys, + .lookup_entry = lib_vrf_lookup_entry, + } + }, + { + .xpath = "/frr-vrf:lib/vrf/state/id", + .cbs = { + .get_elem = lib_vrf_state_id_get_elem, + } + }, + { + .xpath = "/frr-vrf:lib/vrf/state/active", + .cbs = { + .get_elem = lib_vrf_state_active_get_elem, + } + }, + { + .xpath = NULL, + }, + } +}; + diff --git a/lib/vrf.h b/lib/vrf.h index f231d2433fbc..3b02c21823d7 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -322,6 +322,8 @@ extern int vrf_enable(struct vrf *vrf); extern void vrf_delete(struct vrf *vrf); extern vrf_id_t vrf_generate_id(void); +extern const struct frr_yang_module_info frr_vrf_info; + #ifdef __cplusplus } #endif diff --git a/lib/yang.c b/lib/yang.c index 93e6db305530..a0d1695c3994 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -74,6 +74,7 @@ static const char *yang_module_imp_clb(const char *mod_name, static const char *const frr_native_modules[] = { "frr-interface", + "frr-vrf", "frr-ripd", "frr-ripngd", "frr-isisd", diff --git a/yang/frr-vrf.yang b/yang/frr-vrf.yang index 40ead7e79c61..4924a86e89a1 100644 --- a/yang/frr-vrf.yang +++ b/yang/frr-vrf.yang @@ -16,11 +16,13 @@ module frr-vrf { "Initial revision."; } - /* - * Network namespace feature - */ - feature netns { - description "Abstracts network namespace as VRF."; + typedef vrf-ref { + type leafref { + path "/frr-vrf:lib/frr-vrf:vrf/frr-vrf:name"; + require-instance false; + } + description + "Reference to a VRF"; } container lib { @@ -36,40 +38,23 @@ module frr-vrf { "VRF name."; } - leaf id { - type uint32 { - range "0..4294967295"; - } - config false; - description - "VRF Id."; - } - - leaf active { - type boolean; - default "false"; + container state { config false; - description - "VRF active in kernel."; - } + leaf id { + type uint32 { + range "0..4294967295"; + } + description + "VRF Id."; + } - container netns { - if-feature "netns"; - leaf name { - type string; + leaf active { + type boolean; + default "false"; description - "Namespace name."; + "VRF active in kernel."; } } } } - - typedef vrf-ref { - type leafref { - require-instance false; - path "/frr-vrf:lib/frr-vrf:vrf/frr-vrf:name"; - } - description - "Reference to a VRF"; - } } From fc8bee313f1ed9fb203f3f9271654d57191567a2 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Wed, 11 Mar 2020 13:14:08 -0700 Subject: [PATCH 2/5] *: include vrf northbound module in init Signed-off-by: Chirag Shah --- babeld/babel_main.c | 8 ++++---- bfdd/bfdd.c | 1 + bgpd/bgp_main.c | 1 + eigrpd/eigrp_main.c | 1 + isisd/isis_main.c | 1 + ldpd/ldpd.c | 1 + ospf6d/ospf6_main.c | 1 + ospfd/ospf_main.c | 1 + pimd/pim_main.c | 1 + ripd/rip_main.c | 1 + ripngd/ripng_main.c | 1 + sharpd/sharp_main.c | 1 + staticd/static_main.c | 1 + zebra/main.c | 1 + 14 files changed, 17 insertions(+), 4 deletions(-) diff --git a/babeld/babel_main.c b/babeld/babel_main.c index 6f4b905c15ed..e7ba29ed06e4 100644 --- a/babeld/babel_main.c +++ b/babeld/babel_main.c @@ -136,10 +136,10 @@ struct option longopts[] = { 0 } }; -static const struct frr_yang_module_info *const babeld_yang_modules[] = - { - &frr_interface_info, - }; +static const struct frr_yang_module_info *const babeld_yang_modules[] = { + &frr_interface_info, + &frr_vrf_info, +}; FRR_DAEMON_INFO(babeld, BABELD, .vty_port = BABEL_VTY_PORT, diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c index 69f268ab016e..8348be427f30 100644 --- a/bfdd/bfdd.c +++ b/bfdd/bfdd.c @@ -112,6 +112,7 @@ static struct quagga_signal_t bfd_signals[] = { static const struct frr_yang_module_info *const bfdd_yang_modules[] = { &frr_interface_info, &frr_bfdd_info, + &frr_vrf_info, }; FRR_DAEMON_INFO(bfdd, BFD, .vty_port = 2617, diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index c4ece2f082e2..28838d34757c 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -361,6 +361,7 @@ static void bgp_vrf_terminate(void) static const struct frr_yang_module_info *const bgpd_yang_modules[] = { &frr_interface_info, &frr_route_map_info, + &frr_vrf_info, }; FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT, diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index add758fa210a..cdf1c6acdb42 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -141,6 +141,7 @@ static const struct frr_yang_module_info *const eigrpd_yang_modules[] = { &frr_eigrpd_info, &frr_interface_info, &frr_route_map_info, + &frr_vrf_info, }; FRR_DAEMON_INFO(eigrpd, EIGRP, .vty_port = EIGRP_VTY_PORT, diff --git a/isisd/isis_main.c b/isisd/isis_main.c index f7fe089b99a2..4c841dffe2fb 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -168,6 +168,7 @@ static const struct frr_yang_module_info *const isisd_yang_modules[] = { &frr_isisd_info, #endif /* ifndef FABRICD */ &frr_route_map_info, + &frr_vrf_info, }; #ifdef FABRICD diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 78b1c3e54430..bf1e7e696af9 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -180,6 +180,7 @@ static struct quagga_signal_t ldp_signals[] = }; static const struct frr_yang_module_info *const ldpd_yang_modules[] = { + &frr_vrf_info, }; FRR_DAEMON_INFO(ldpd, LDP, diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index e4bed7a79d0a..4dbe5ca321f5 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -168,6 +168,7 @@ struct quagga_signal_t ospf6_signals[] = { static const struct frr_yang_module_info *const ospf6d_yang_modules[] = { &frr_interface_info, &frr_route_map_info, + &frr_vrf_info, }; FRR_DAEMON_INFO(ospf6d, OSPF6, .vty_port = OSPF6_VTY_PORT, diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 4d6ebb40eb04..6a3ba9902d50 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -128,6 +128,7 @@ struct quagga_signal_t ospf_signals[] = { static const struct frr_yang_module_info *const ospfd_yang_modules[] = { &frr_interface_info, &frr_route_map_info, + &frr_vrf_info, }; FRR_DAEMON_INFO(ospfd, OSPF, .vty_port = OSPF_VTY_PORT, diff --git a/pimd/pim_main.c b/pimd/pim_main.c index 93b561ba0f39..5c4c7151a534 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -75,6 +75,7 @@ struct zebra_privs_t pimd_privs = { static const struct frr_yang_module_info *const pimd_yang_modules[] = { &frr_interface_info, &frr_route_map_info, + &frr_vrf_info, }; FRR_DAEMON_INFO(pimd, PIM, .vty_port = PIMD_VTY_PORT, diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 73e94deefccd..9ec32a53e306 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -117,6 +117,7 @@ static const struct frr_yang_module_info *const ripd_yang_modules[] = { &frr_interface_info, &frr_ripd_info, &frr_route_map_info, + &frr_vrf_info, }; FRR_DAEMON_INFO(ripd, RIP, .vty_port = RIP_VTY_PORT, diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index 99adb2cba740..fbac750db3bf 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -117,6 +117,7 @@ static const struct frr_yang_module_info *const ripngd_yang_modules[] = { &frr_interface_info, &frr_ripngd_info, &frr_route_map_info, + &frr_vrf_info, }; FRR_DAEMON_INFO(ripngd, RIPNG, .vty_port = RIPNG_VTY_PORT, diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c index 5133523f018a..120d7049189e 100644 --- a/sharpd/sharp_main.c +++ b/sharpd/sharp_main.c @@ -114,6 +114,7 @@ struct quagga_signal_t sharp_signals[] = { static const struct frr_yang_module_info *const sharpd_yang_modules[] = { &frr_interface_info, &frr_route_map_info, + &frr_vrf_info, }; FRR_DAEMON_INFO(sharpd, SHARP, .vty_port = SHARP_VTY_PORT, diff --git a/staticd/static_main.c b/staticd/static_main.c index 3aa8a8db3ebb..c77a99f28049 100644 --- a/staticd/static_main.c +++ b/staticd/static_main.c @@ -104,6 +104,7 @@ struct quagga_signal_t static_signals[] = { }; static const struct frr_yang_module_info *const staticd_yang_modules[] = { + &frr_vrf_info, }; #define STATIC_VTY_PORT 2616 diff --git a/zebra/main.c b/zebra/main.c index dab14491940d..3de178567a47 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -245,6 +245,7 @@ struct quagga_signal_t zebra_signals[] = { static const struct frr_yang_module_info *const zebra_yang_modules[] = { &frr_interface_info, &frr_route_map_info, + &frr_vrf_info, }; FRR_DAEMON_INFO( From 4d780b129691b872e222341f06326ff6e3d7e20c Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Sat, 21 Mar 2020 14:35:14 -0700 Subject: [PATCH 3/5] lib: convert vrf cmd to northbound config callback Signed-off-by: Chirag Shah --- lib/vrf.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/lib/vrf.c b/lib/vrf.c index 9346771b05e1..6f04e2300e0b 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -37,6 +37,7 @@ #include "nexthop_group.h" #include "lib_errors.h" #include "northbound.h" +#include "northbound_cli.h" /* default VRF ID value used when VRF backend is not NETNS */ #define VRF_DEFAULT_INTERNAL 0 @@ -604,6 +605,8 @@ int vrf_handler_create(struct vty *vty, const char *vrfname, struct vrf **vrf) { struct vrf *vrfp; + char xpath_list[XPATH_MAXLEN]; + int ret; if (strlen(vrfname) > VRF_NAMSIZ) { if (vty) @@ -618,13 +621,24 @@ int vrf_handler_create(struct vty *vty, const char *vrfname, return CMD_WARNING_CONFIG_FAILED; } - vrfp = vrf_get(VRF_UNKNOWN, vrfname); - - if (vty) - VTY_PUSH_CONTEXT(VRF_NODE, vrfp); + if (vty) { + snprintf(xpath_list, sizeof(xpath_list), + "/frr-vrf:lib/vrf[name='%s']", vrfname); + + nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL); + ret = nb_cli_apply_changes(vty, xpath_list); + if (ret == CMD_SUCCESS) { + VTY_PUSH_XPATH(VRF_NODE, xpath_list); + vrfp = vrf_lookup_by_name(vrfname); + if (vrfp) + VTY_PUSH_CONTEXT(VRF_NODE, vrfp); + } + } else { + vrfp = vrf_get(VRF_UNKNOWN, vrfname); - if (vrf) - *vrf = vrfp; + if (vrf) + *vrf = vrfp; + } return CMD_SUCCESS; } @@ -727,6 +741,7 @@ DEFUN (no_vrf, "VRF's name\n") { const char *vrfname = argv[2]->arg; + char xpath_list[XPATH_MAXLEN]; struct vrf *vrfp; @@ -742,11 +757,11 @@ DEFUN (no_vrf, return CMD_WARNING_CONFIG_FAILED; } - /* Clear configured flag and invoke delete. */ - UNSET_FLAG(vrfp->status, VRF_CONFIGURED); - vrf_delete(vrfp); + snprintf(xpath_list, sizeof(xpath_list), "/frr-vrf:lib/vrf[name='%s']", + vrfname); - return CMD_SUCCESS; + nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, xpath_list); } @@ -1039,7 +1054,6 @@ static int lib_vrf_destroy(enum nb_event event, const struct lyd_node *dnode) { struct vrf *vrfp; - switch (event) { case NB_EV_VALIDATE: vrfp = nb_running_get_entry(dnode, NULL, true); @@ -1054,6 +1068,7 @@ static int lib_vrf_destroy(enum nb_event event, const struct lyd_node *dnode) break; case NB_EV_APPLY: vrfp = nb_running_unset_entry(dnode); + /* Clear configured flag and invoke delete. */ UNSET_FLAG(vrfp->status, VRF_CONFIGURED); vrf_delete(vrfp); From 93624af97323ac4a189e2278bdc97631e845a17d Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Sat, 21 Mar 2020 16:46:24 -0700 Subject: [PATCH 4/5] yang: revert leafref to get interface cmd working Unable to access interface command: root@bharat:~/stash/libyang/build# dpkg-query -W | grep libyang libyang-dev 0.16.105-3~ubuntu18.04.1 libyang0.16 0.16.105-3~ubuntu18.04.1 root@bharat:~/stash/libyang/build# vtysh bharat# config t bharat(config)# interface lo % Configuration failed: validation error. Please check the logs for more details. Logfile: 2020/03/21 16:48:55 ZEBRA: libyang: Leafref "/frr-vrf:lib/frr-vrf:vrf/frr-vrf:name" of value "default" points to a non-existing leaf. (/frr-interface:lib/interface[name='lo'][vrf='default']/vrf) 2020/03/21 16:48:55 ZEBRA: [EC 100663337] nb_candidate_commit_prepare: failed to validate candidate configuration CI system failure: 2020/03/21 18:53:18 ZEBRA: libyang: Leafref "/frr-vrf:lib/frr-vrf:vrf/frr-vrf:name" of value "default" points to a non-existing leaf. (/frr-interface:lib/interface[name='r1-eth0'][vrf='default']/vrf) 2020/03/21 18:53:18 ZEBRA: [EC 100663337] nb_candidate_commit_prepare: failed to validate candidate configuration 2020/03/21 18:53:18 ZEBRA: libyang: Leafref "/frr-vrf:lib/frr-vrf:vrf/frr-vrf:name" of value "default" points to a non-existing leaf. (/frr-interface:lib/interface[name='r1-eth1'][vrf='default']/vrf) Signed-off-by: Chirag Shah --- yang/frr-interface.yang | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yang/frr-interface.yang b/yang/frr-interface.yang index c7031ed41d33..23b4324d5ae4 100644 --- a/yang/frr-interface.yang +++ b/yang/frr-interface.yang @@ -38,7 +38,11 @@ module frr-interface { } leaf vrf { - type frr-vrf:vrf-ref; + type string { + length "1..16"; + } + /* yang version 0.16 having issue accessing leafref. */ + /* type frr-vrf:vrf-ref;*/ description "VRF this interface is associated with."; } From 2209fc5839d0ca69fc184c2a5379f5ce942125aa Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Tue, 24 Mar 2020 13:14:25 -0700 Subject: [PATCH 5/5] lib: static yang array size gcc 4 workaround gcc 4 variable size array is not calcualated properely As an example, on Centos 7, yang module fails to load upon daemon start. Signed-off-by: chirag shah --- lib/northbound.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/northbound.h b/lib/northbound.h index 76a11e518cc0..fd549d5f96fa 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -417,7 +417,11 @@ struct frr_yang_module_info { /* Priority - lower priorities are processed first. */ uint32_t priority; +#if defined(__GNUC__) && ((__GNUC__ - 0) < 5) && !defined(__clang__) + } nodes[1000]; +#else } nodes[]; +#endif }; /* Northbound error codes. */