From 09268680bb99f237517281638aecba740ed20e94 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Mon, 24 Feb 2020 18:40:29 -0800 Subject: [PATCH] zebra: add northbound support for zebra interface Signed-off-by: Chirag Shah --- zebra/interface.c | 302 +++++++++++++++++++++++++++++++++++++--- zebra/interface.h | 11 ++ zebra/zebra_nb_config.c | 216 +++++++++++++++++++--------- zebra/zebra_nb_state.c | 69 +++++++-- 4 files changed, 499 insertions(+), 99 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index 59cbfc6854..7c0bddfadd 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -500,7 +500,7 @@ void if_flags_update(struct interface *ifp, uint64_t newflags) /* Wake up configured address if it is not in current kernel address. */ -static void if_addr_wakeup(struct interface *ifp) +void if_addr_wakeup(struct interface *ifp) { struct listnode *node, *nnode; struct connected *ifc; @@ -1881,6 +1881,24 @@ DEFUN (show_interface_desc_vrf_all, return CMD_SUCCESS; } +int if_multicast_set(struct interface *ifp) +{ + struct zebra_if *if_data; + + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + if (if_set_flags(ifp, IFF_MULTICAST) < 0) { + zlog_debug("Can't set multicast flag on interface %s", + ifp->name); + return -1; + } + if_refresh(ifp); + } + if_data = ifp->info; + if_data->multicast = IF_ZEBRA_MULTICAST_ON; + + return 0; +} + DEFUN (multicast, multicast_cmd, "multicast", @@ -1904,6 +1922,24 @@ DEFUN (multicast, return CMD_SUCCESS; } +int if_multicast_unset(struct interface *ifp) +{ + struct zebra_if *if_data; + + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + if (if_unset_flags(ifp, IFF_MULTICAST) < 0) { + zlog_debug("Can't unset multicast flag on interface %s", + ifp->name); + return -1; + } + if_refresh(ifp); + } + if_data = ifp->info; + if_data->multicast = IF_ZEBRA_MULTICAST_OFF; + + return 0; +} + DEFUN (no_multicast, no_multicast_cmd, "no multicast", @@ -1928,23 +1964,35 @@ DEFUN (no_multicast, return CMD_SUCCESS; } -DEFUN (linkdetect, - linkdetect_cmd, - "link-detect", - "Enable link detection on interface\n") +int if_linkdetect(struct interface *ifp, bool detect) { - VTY_DECLVAR_CONTEXT(interface, ifp); int if_was_operative; if_was_operative = if_is_no_ptm_operative(ifp); - SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); + if (detect) { + SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); - /* When linkdetection is enabled, if might come down */ - if (!if_is_no_ptm_operative(ifp) && if_was_operative) - if_down(ifp); + /* When linkdetection is enabled, if might come down */ + if (!if_is_no_ptm_operative(ifp) && if_was_operative) + if_down(ifp); + } else { + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); + /* Interface may come up after disabling link detection */ + if (if_is_operative(ifp) && !if_was_operative) + if_up(ifp); + } /* FIXME: Will defer status change forwarding if interface does not come down! */ + return 0; +} + +DEFUN(linkdetect, linkdetect_cmd, "link-detect", + "Enable link detection on interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + + if_linkdetect(ifp, true); return CMD_SUCCESS; } @@ -1957,18 +2005,29 @@ DEFUN (no_linkdetect, "Disable link detection on interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); - int if_was_operative; - if_was_operative = if_is_no_ptm_operative(ifp); - UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); + if_linkdetect(ifp, false); + + return CMD_SUCCESS; +} - /* Interface may come up after disabling link detection */ - if (if_is_operative(ifp) && !if_was_operative) - if_up(ifp); +int if_shutdown(struct interface *ifp) +{ + struct zebra_if *if_data; - /* FIXME: see linkdetect_cmd */ + if (ifp->ifindex != IFINDEX_INTERNAL) { + /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */ + rtadv_stop_ra(ifp); + if (if_unset_flags(ifp, IFF_UP) < 0) { + zlog_debug("Can't shutdown interface %s", ifp->name); + return -1; + } + if_refresh(ifp); + } + if_data = ifp->info; + if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON; - return CMD_SUCCESS; + return 0; } DEFUN (shutdown_if, @@ -1996,6 +2055,30 @@ DEFUN (shutdown_if, return CMD_SUCCESS; } +int if_no_shutdown(struct interface *ifp) +{ + struct zebra_if *if_data; + + if (ifp->ifindex != IFINDEX_INTERNAL) { + if (if_set_flags(ifp, IFF_UP | IFF_RUNNING) < 0) { + zlog_debug("Can't up interface %s", ifp->name); + return -1; + } + if_refresh(ifp); + + /* Some addresses (in particular, IPv6 addresses on Linux) get + * removed when the interface goes down. They need to be + * readded. + */ + if_addr_wakeup(ifp); + } + + if_data = ifp->info; + if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF; + + return 0; +} + DEFUN (no_shutdown_if, no_shutdown_if_cmd, "no shutdown", @@ -2748,6 +2831,79 @@ DEFUN (no_link_params_use_bw, return CMD_SUCCESS; } +int if_ip_address_install(struct interface *ifp, struct prefix *prefix, + const char *label, struct prefix *pp) +{ + struct zebra_if *if_data; + struct prefix_ipv4 lp; + struct prefix_ipv4 *p; + struct connected *ifc; + enum zebra_dplane_result dplane_res; + + if_data = ifp->info; + + lp.family = prefix->family; + lp.prefix = prefix->u.prefix4; + lp.prefixlen = prefix->prefixlen; + apply_mask_ipv4(&lp); + + ifc = connected_check_ptp(ifp, &lp, pp ? pp : NULL); + if (!ifc) { + ifc = connected_new(); + ifc->ifp = ifp; + + /* Address. */ + p = prefix_ipv4_new(); + *p = lp; + ifc->address = (struct prefix *)p; + + if (pp) { + SET_FLAG(ifc->flags, ZEBRA_IFA_PEER); + p = prefix_ipv4_new(); + *p = *(struct prefix_ipv4 *)pp; + ifc->destination = (struct prefix *)p; + } + + /* Label. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); + + /* Add to linked list. */ + listnode_add(ifp->connected, ifc); + } + + /* This address is configured from zebra. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* In case of this route need to install kernel. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) + && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + /* Some system need to up the interface to set IP address. */ + if (!if_is_up(ifp)) { + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + dplane_res = dplane_intf_addr_set(ifp, ifc); + if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { + zlog_debug( + "dplane can't set interface IP address: %s.\n", + dplane_res2str(dplane_res)); + return NB_ERR; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the + * notification + * from the kernel has been received. + * It will also be added to the subnet chain list, then. */ + } + + return 0; +} + static int ip_address_install(struct vty *vty, struct interface *ifp, const char *addr_str, const char *peer_str, const char *label) @@ -2842,6 +2998,51 @@ static int ip_address_install(struct vty *vty, struct interface *ifp, return CMD_SUCCESS; } +int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix) +{ + struct connected *ifc = NULL; + enum zebra_dplane_result dplane_res; + + if (prefix->family == AF_INET) { + /* Check current interface address. */ + ifc = connected_check_ptp(ifp, prefix, NULL); + if (!ifc) { + zlog_debug("interface %s Can't find address\n", + ifp->name); + return -1; + } + + } else if (prefix->family == AF_INET6) { + /* Check current interface address. */ + ifc = connected_check(ifp, prefix); + } + + if (!ifc) { + zlog_debug("interface %s Can't find address\n", ifp->name); + return -1; + } + UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* This is not real address or interface is not active. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + listnode_delete(ifp->connected, ifc); + connected_free(&ifc); + return CMD_WARNING_CONFIG_FAILED; + } + + /* This is real route. */ + dplane_res = dplane_intf_addr_unset(ifp, ifc); + if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { + zlog_debug("Can't unset interface IP address: %s.\n", + dplane_res2str(dplane_res)); + return -1; + } + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + + return 0; +} + static int ip_address_uninstall(struct vty *vty, struct interface *ifp, const char *addr_str, const char *peer_str, const char *label) @@ -2995,6 +3196,71 @@ DEFUN (no_ip_address_label, } #endif /* HAVE_NETLINK */ +int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix, + const char *label) +{ + struct zebra_if *if_data; + struct prefix_ipv6 cp; + struct connected *ifc; + struct prefix_ipv6 *p; + enum zebra_dplane_result dplane_res; + + if_data = ifp->info; + + cp.family = prefix->family; + cp.prefixlen = prefix->prefixlen; + cp.prefix = prefix->u.prefix6; + apply_mask_ipv6(&cp); + + ifc = connected_check(ifp, (struct prefix *)&cp); + if (!ifc) { + ifc = connected_new(); + ifc->ifp = ifp; + + /* Address. */ + p = prefix_ipv6_new(); + *p = cp; + ifc->address = (struct prefix *)p; + + /* Label. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); + + /* Add to linked list. */ + listnode_add(ifp->connected, ifc); + } + + /* This address is configured from zebra. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* In case of this route need to install kernel. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) + && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + /* Some system need to up the interface to set IP address. */ + if (!if_is_up(ifp)) { + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + dplane_res = dplane_intf_addr_set(ifp, ifc); + if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { + zlog_debug( + "dplane can't set interface IP address: %s.\n", + dplane_res2str(dplane_res)); + return NB_ERR; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the + * notification + * from the kernel has been received. */ + } + + return 0; +} + static int ipv6_address_install(struct vty *vty, struct interface *ifp, const char *addr_str, const char *peer_str, const char *label) diff --git a/zebra/interface.h b/zebra/interface.h index b7e90a0c31..80799b58a1 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -440,6 +440,17 @@ extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex, ns_id_t ns_id); extern void zebra_if_update_all_links(void); extern void zebra_if_set_protodown(struct interface *ifp, bool down); +extern int if_ip_address_install(struct interface *ifp, struct prefix *prefix, + const char *label, struct prefix *pp); +extern int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix, + const char *label); +extern int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix); +extern int if_shutdown(struct interface *ifp); +extern int if_no_shutdown(struct interface *ifp); +extern int if_multicast_set(struct interface *ifp); +extern int if_multicast_unset(struct interface *ifp); +extern int if_linkdetect(struct interface *ifp, bool detect); +extern void if_addr_wakeup(struct interface *ifp); /* Nexthop group connected functions */ extern void if_nhg_dependents_add(struct interface *ifp, diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c index 5140a2bbfa..311922f2ef 100644 --- a/zebra/zebra_nb_config.c +++ b/zebra/zebra_nb_config.c @@ -24,9 +24,11 @@ #include "libfrr.h" #include "lib/command.h" #include "lib/routemap.h" - #include "zebra/zebra_nb.h" #include "zebra/rib.h" +#include "zebra_nb.h" +#include "zebra/interface.h" +#include "zebra/connected.h" /* * XPath: /frr-zebra:zebra/mcast-rpf-lookup @@ -1013,12 +1015,38 @@ int lib_interface_zebra_ip_addrs_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct interface *ifp; + struct prefix prefix; + char buf[PREFIX_STRLEN] = {0}; + + ifp = nb_running_get_entry(dnode, NULL, true); + // addr_family = yang_dnode_get_enum(dnode, "./address-family"); + yang_dnode_get_prefix(&prefix, dnode, "./ip-prefix"); + apply_mask(&prefix); + switch (event) { case NB_EV_VALIDATE: + if (prefix.family == AF_INET + && ipv4_martian(&prefix.u.prefix4)) { + zlog_debug("invalid address %s", + prefix2str(&prefix, buf, sizeof(buf))); + return NB_ERR_VALIDATION; + } else if (prefix.family == AF_INET6 + && ipv6_martian(&prefix.u.prefix6)) { + zlog_debug("invalid address %s", + prefix2str(&prefix, buf, sizeof(buf))); + return NB_ERR_VALIDATION; + } + break; case NB_EV_PREPARE: case NB_EV_ABORT: + break; case NB_EV_APPLY: - /* TODO: implement me. */ + if (prefix.family == AF_INET) + if_ip_address_install(ifp, &prefix, NULL, NULL); + else if (prefix.family == AF_INET6) + if_ipv6_address_install(ifp, &prefix, NULL); + break; } @@ -1028,12 +1056,54 @@ int lib_interface_zebra_ip_addrs_create(enum nb_event event, int lib_interface_zebra_ip_addrs_destroy(enum nb_event event, const struct lyd_node *dnode) { - switch (event) { - case NB_EV_VALIDATE: + struct interface *ifp; + struct prefix prefix; + struct connected *ifc; + + ifp = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_prefix(&prefix, dnode, "./ip-prefix"); + apply_mask(&prefix); + + switch (event) { + case NB_EV_VALIDATE: + if (prefix.family == AF_INET) { + /* Check current interface address. */ + ifc = connected_check_ptp(ifp, &prefix, NULL); + if (!ifc) { + zlog_debug("interface %s Can't find address\n", + ifp->name); + return NB_ERR_VALIDATION; + } + } else if (prefix.family == AF_INET6) { + /* Check current interface address. */ + ifc = connected_check(ifp, &prefix); + if (!ifc) { + zlog_debug("interface can't find address %s", + ifp->name); + return NB_ERR_VALIDATION; + } + } else + return NB_ERR_VALIDATION; + + /* This is not configured address. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) { + zlog_debug("interface %s not configured", ifp->name); + return NB_ERR_VALIDATION; + } + + /* This is not real address or interface is not active. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + listnode_delete(ifp->connected, ifc); + connected_free(&ifc); + return NB_ERR_VALIDATION; + } + break; case NB_EV_PREPARE: case NB_EV_ABORT: + break; case NB_EV_APPLY: - /* TODO: implement me. */ + if_ip_address_uinstall(ifp, &prefix); break; } @@ -1115,14 +1185,14 @@ int lib_interface_zebra_multicast_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (event != NB_EV_APPLY) + return NB_OK; + + struct interface *ifp; + + ifp = nb_running_get_entry(dnode, NULL, true); + + if_multicast_set(ifp); return NB_OK; } @@ -1130,14 +1200,14 @@ int lib_interface_zebra_multicast_modify(enum nb_event event, int lib_interface_zebra_multicast_destroy(enum nb_event event, const struct lyd_node *dnode) { - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (event != NB_EV_APPLY) + return NB_OK; + + struct interface *ifp; + + ifp = nb_running_get_entry(dnode, NULL, true); + + if_multicast_unset(ifp); return NB_OK; } @@ -1149,14 +1219,16 @@ int lib_interface_zebra_link_detect_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (event != NB_EV_APPLY) + return NB_OK; + + struct interface *ifp; + bool link_detect; + + ifp = nb_running_get_entry(dnode, NULL, true); + link_detect = yang_dnode_get_bool(dnode, "./link-detect"); + + if_linkdetect(ifp, link_detect); return NB_OK; } @@ -1164,14 +1236,16 @@ int lib_interface_zebra_link_detect_modify(enum nb_event event, int lib_interface_zebra_link_detect_destroy(enum nb_event event, const struct lyd_node *dnode) { - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (event != NB_EV_APPLY) + return NB_OK; + + struct interface *ifp; + bool link_detect; + + ifp = nb_running_get_entry(dnode, NULL, true); + link_detect = yang_dnode_get_bool(dnode, "./link-detect"); + + if_linkdetect(ifp, link_detect); return NB_OK; } @@ -1183,14 +1257,11 @@ int lib_interface_zebra_shutdown_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct interface *ifp; + + ifp = nb_running_get_entry(dnode, NULL, true); + + if_shutdown(ifp); return NB_OK; } @@ -1198,14 +1269,11 @@ int lib_interface_zebra_shutdown_modify(enum nb_event event, int lib_interface_zebra_shutdown_destroy(enum nb_event event, const struct lyd_node *dnode) { - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct interface *ifp; + + ifp = nb_running_get_entry(dnode, NULL, true); + + if_no_shutdown(ifp); return NB_OK; } @@ -1217,14 +1285,20 @@ int lib_interface_zebra_bandwidth_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (event != NB_EV_APPLY) + return NB_OK; + + struct interface *ifp; + uint32_t bandwidth; + + ifp = nb_running_get_entry(dnode, NULL, true); + bandwidth = yang_dnode_get_uint32(dnode, "./bandwidth"); + + ifp->bandwidth = bandwidth; + + /* force protocols to recalculate routes due to cost change */ + if (if_is_operative(ifp)) + zebra_interface_up_update(ifp); return NB_OK; } @@ -1232,14 +1306,18 @@ int lib_interface_zebra_bandwidth_modify(enum nb_event event, int lib_interface_zebra_bandwidth_destroy(enum nb_event event, const struct lyd_node *dnode) { - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (event != NB_EV_APPLY) + return NB_OK; + + struct interface *ifp; + + ifp = nb_running_get_entry(dnode, NULL, true); + + ifp->bandwidth = 0; + + /* force protocols to recalculate routes due to cost change */ + if (if_is_operative(ifp)) + zebra_interface_up_update(ifp); return NB_OK; } diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c index 925f90b7c2..788998106e 100644 --- a/zebra/zebra_nb_state.c +++ b/zebra/zebra_nb_state.c @@ -21,6 +21,7 @@ #include "northbound.h" #include "libfrr.h" #include "zebra_nb.h" +#include "zebra/interface.h" /* * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/up-count @@ -29,8 +30,12 @@ struct yang_data * lib_interface_zebra_state_up_count_get_elem(const char *xpath, const void *list_entry) { - /* TODO: implement me. */ - return NULL; + const struct interface *ifp = list_entry; + struct zebra_if *zebra_if; + + zebra_if = ifp->info; + + return yang_data_new_uint16(xpath, zebra_if->up_count); } /* @@ -40,8 +45,12 @@ struct yang_data * lib_interface_zebra_state_down_count_get_elem(const char *xpath, const void *list_entry) { - /* TODO: implement me. */ - return NULL; + const struct interface *ifp = list_entry; + struct zebra_if *zebra_if; + + zebra_if = ifp->info; + + return yang_data_new_uint16(xpath, zebra_if->down_count); } /* @@ -73,8 +82,17 @@ struct yang_data * lib_interface_zebra_state_vlan_id_get_elem(const char *xpath, const void *list_entry) { - /* TODO: implement me. */ - return NULL; + const struct interface *ifp = list_entry; + struct zebra_if *zebra_if; + struct zebra_l2info_vlan *vlan_info; + + if (!IS_ZEBRA_IF_VLAN(ifp)) + return NULL; + + zebra_if = ifp->info; + vlan_info = &zebra_if->l2info.vl; + + return yang_data_new_uint16(xpath, vlan_info->vid); } /* @@ -84,8 +102,17 @@ struct yang_data * lib_interface_zebra_state_vni_id_get_elem(const char *xpath, const void *list_entry) { - /* TODO: implement me. */ - return NULL; + const struct interface *ifp = list_entry; + struct zebra_if *zebra_if; + struct zebra_l2info_vxlan *vxlan_info; + + if (!IS_ZEBRA_IF_VXLAN(ifp)) + return NULL; + + zebra_if = ifp->info; + vxlan_info = &zebra_if->l2info.vxl; + + return yang_data_new_uint32(xpath, vxlan_info->vni); } /* @@ -95,8 +122,17 @@ struct yang_data * lib_interface_zebra_state_remote_vtep_get_elem(const char *xpath, const void *list_entry) { - /* TODO: implement me. */ - return NULL; + const struct interface *ifp = list_entry; + struct zebra_if *zebra_if; + struct zebra_l2info_vxlan *vxlan_info; + + if (!IS_ZEBRA_IF_VXLAN(ifp)) + return NULL; + + zebra_if = ifp->info; + vxlan_info = &zebra_if->l2info.vxl; + + return yang_data_new_ipv4(xpath, &vxlan_info->vtep_ip); } /* @@ -106,8 +142,17 @@ struct yang_data * lib_interface_zebra_state_mcast_group_get_elem(const char *xpath, const void *list_entry) { - /* TODO: implement me. */ - return NULL; + const struct interface *ifp = list_entry; + struct zebra_if *zebra_if; + struct zebra_l2info_vxlan *vxlan_info; + + if (!IS_ZEBRA_IF_VXLAN(ifp)) + return NULL; + + zebra_if = ifp->info; + vxlan_info = &zebra_if->l2info.vxl; + + return yang_data_new_ipv4(xpath, &vxlan_info->mcast_grp); } const void *lib_vrf_ribs_rib_get_next(const void *parent_list_entry, -- 2.39.5