]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: add northbound support for zebra interface
authorChirag Shah <chirag@cumulusnetworks.com>
Tue, 25 Feb 2020 02:40:29 +0000 (18:40 -0800)
committerSantosh P K <sapk@vmware.com>
Thu, 16 Apr 2020 15:51:38 +0000 (08:51 -0700)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
zebra/interface.c
zebra/interface.h
zebra/zebra_nb_config.c
zebra/zebra_nb_state.c

index 59cbfc6854559cf6a4b99841ff94fade1339b5f7..7c0bddfadd67926484ee1decbae82aef4d80ee88 100644 (file)
@@ -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)
index b7e90a0c31edcbadbb9afd55f6872698fe606855..80799b58a1531196ff931b5be5e316f47dce395b 100644 (file)
@@ -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,
index 5140a2bbfa0b5f4b9c8b2eb09c526335b97abe20..311922f2effe1572e02a7eaa59033166c87d82cd 100644 (file)
 #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;
 }
index 925f90b7c275385ec829430174628cadbc47c0e3..788998106e21598b25bf44e96a58a456223bf486 100644 (file)
@@ -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,