/* 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;
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",
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",
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;
}
"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,
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",
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)
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)
}
#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)
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,
#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
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
#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
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);
}
/*
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);
}
/*
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);
}
/*
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);
}
/*
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);
}
/*
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,