]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: convert interface ip/ipv6 address commands to NB
authorIgor Ryzhov <iryzhov@nfware.com>
Thu, 18 Jan 2024 18:21:00 +0000 (20:21 +0200)
committerIgor Ryzhov <iryzhov@nfware.com>
Sun, 28 Jan 2024 21:28:39 +0000 (23:28 +0200)
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
yang/frr-zebra.yang
zebra/interface.c
zebra/interface.h
zebra/zebra_nb.c
zebra/zebra_nb.h
zebra/zebra_nb_config.c

index 23b243889abc9a53efa95bd05889e48decc8eb05..14c6ae5f77b0af214a64963d3e7961254998e0de 100644 (file)
@@ -1935,19 +1935,23 @@ module frr-zebra {
     description
       "Extends interface model with Zebra-related parameters.";
     container zebra {
-      list ip-addrs {
-        key "address-family ip-prefix";
+      list ipv4-addrs {
+        key "ip prefix-length";
         description
-          "IP prefixes for an interface.";
-        uses frr-rt:address-family {
+          "The list of configured IPv4 addresses on the interface.";
+
+        leaf ip {
+          type inet:ipv4-address-no-zone;
           description
-            "Address family of the RIB.";
+            "The IPv4 address on the interface.";
         }
 
-        leaf ip-prefix {
-          type inet:ip-prefix;
+        leaf prefix-length {
+          type uint8 {
+            range "0..32";
+          }
           description
-            "IP address prefix.";
+            "The length of the subnet prefix.";
         }
 
         leaf label {
@@ -1955,12 +1959,57 @@ module frr-zebra {
           description
             "Optional string label for the address.";
         }
+      }
 
-        leaf ip4-peer {
-          when "derived-from-or-self(../address-family, 'frr-rt:ipv4')";
-          type inet:ipv4-prefix;
+      list ipv4-p2p-addrs {
+        key "ip peer-ip peer-prefix-length";
+        description
+          "The list of configured peer-to-peer IPv4 addresses on the interface.";
+
+        leaf ip {
+          type inet:ipv4-address-no-zone;
+          description
+            "The IPv4 address on the interface.";
+        }
+
+        leaf peer-ip {
+          type inet:ipv4-address-no-zone;
+          description
+            "Peer address.";
+        }
+
+        leaf peer-prefix-length {
+          type uint8 {
+            range "0..32";
+          }
+          description
+            "The length of the peer subnet prefix.";
+        }
+
+        leaf label {
+          type string;
+          description
+            "Optional string label for the address.";
+        }
+      }
+
+      list ipv6-addrs {
+        key "ip prefix-length";
+        description
+          "The list of configured IPv6 addresses on the interface.";
+
+        leaf ip {
+          type inet:ipv6-address-no-zone;
+          description
+            "The IPv6 address on the interface.";
+        }
+
+        leaf prefix-length {
+          type uint8 {
+            range "0..128";
+          }
           description
-            "Peer prefix, for peer-to-peer interfaces.";
+            "The length of the subnet prefix.";
         }
       }
 
index 38e4ae2e00f27d65a206bc317c9942dd191daed9..31bb06ed1c237fce962898d9662cb5e267c06dc6 100644 (file)
@@ -4732,37 +4732,27 @@ void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode,
        vty_out(vty, "\n");
 }
 
-int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
-                         const char *label, struct prefix *pp)
+void 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);
+       ifc = connected_check_ptp(ifp, prefix, pp);
        if (!ifc) {
                ifc = connected_new();
                ifc->ifp = ifp;
 
                /* Address. */
-               p = prefix_ipv4_new();
-               *p = lp;
-               ifc->address = (struct prefix *)p;
+               ifc->address = prefix_new();
+               prefix_copy(ifc->address, prefix);
 
                if (pp) {
                        SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
-                       p = prefix_ipv4_new();
-                       *p = *(struct prefix_ipv4 *)pp;
-                       ifc->destination = (struct prefix *)p;
+                       ifc->destination = prefix_new();
+                       prefix_copy(ifc->destination, pp);
                }
 
                /* Label. */
@@ -4787,13 +4777,7 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
                        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.",
-                               dplane_res2str(dplane_res));
-                       return NB_ERR;
-               }
+               dplane_intf_addr_set(ifp, ifc);
 
                SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
                /* The address will be advertised to zebra clients when the
@@ -4801,127 +4785,16 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
                 * 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)
+void if_ip_address_uninstall(struct interface *ifp, struct prefix *prefix,
+                            struct prefix *pp)
 {
-       struct zebra_if *if_data;
-       struct prefix_ipv4 lp, pp;
        struct connected *ifc;
-       struct prefix_ipv4 *p;
-       int ret;
-       enum zebra_dplane_result dplane_res;
-
-       if_data = ifp->info;
-
-       ret = str2prefix_ipv4(addr_str, &lp);
-       if (ret <= 0) {
-               vty_out(vty, "%% Malformed address \n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (ipv4_martian(&lp.prefix)) {
-               vty_out(vty, "%% Invalid address\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (peer_str) {
-               if (lp.prefixlen != IPV4_MAX_BITLEN) {
-                       vty_out(vty,
-                               "%% Local prefix length for P-t-P address must be /32\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               ret = str2prefix_ipv4(peer_str, &pp);
-               if (ret <= 0) {
-                       vty_out(vty, "%% Malformed peer address\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-       }
-
-       ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
-       if (!ifc) {
-               ifc = connected_new();
-               ifc->ifp = ifp;
-
-               /* Address. */
-               p = prefix_ipv4_new();
-               *p = lp;
-               ifc->address = (struct prefix *)p;
-
-               if (peer_str) {
-                       SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
-                       p = prefix_ipv4_new();
-                       *p = pp;
-                       ifc->destination = (struct prefix *)p;
-               }
-
-               /* Label. */
-               if (label)
-                       ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
-
-               /* Add to linked list. */
-               if_connected_add_tail(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_DATA_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) {
-                       vty_out(vty, "%% Can't set interface IP address: %s.\n",
-                               dplane_res2str(dplane_res));
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               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 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",
-                                  ifp->name);
-                       return -1;
-               }
-
-       } else if (prefix->family == AF_INET6) {
-               /* Check current interface address. */
-               ifc = connected_check(ifp, prefix);
-       }
+       ifc = connected_check_ptp(ifp, prefix, pp);
+       assert(ifc);
 
-       if (!ifc) {
-               zlog_debug("interface %s Can't find address", ifp->name);
-               return -1;
-       }
        UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
 
        /* This is not real address or interface is not active. */
@@ -4929,276 +4802,131 @@ int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix)
            || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
                if_connected_del(ifp->connected, ifc);
                connected_free(&ifc);
-               return CMD_WARNING_CONFIG_FAILED;
+               return;
        }
 
        /* 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.",
-                          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)
-{
-       struct prefix_ipv4 lp, pp;
-       struct connected *ifc;
-       int ret;
-       enum zebra_dplane_result dplane_res;
-
-       /* Convert to prefix structure. */
-       ret = str2prefix_ipv4(addr_str, &lp);
-       if (ret <= 0) {
-               vty_out(vty, "%% Malformed address \n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (peer_str) {
-               if (lp.prefixlen != IPV4_MAX_BITLEN) {
-                       vty_out(vty,
-                               "%% Local prefix length for P-t-P address must be /32\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               ret = str2prefix_ipv4(peer_str, &pp);
-               if (ret <= 0) {
-                       vty_out(vty, "%% Malformed peer address\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-       }
-
-       /* Check current interface address. */
-       ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
-       if (!ifc) {
-               vty_out(vty, "%% Can't find address\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       /* This is not configured address. */
-       if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
-               return CMD_WARNING_CONFIG_FAILED;
-
-       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)) {
-               if_connected_del(ifp->connected, ifc);
-               connected_free(&ifc);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
+       dplane_intf_addr_unset(ifp, ifc);
 
-       /* This is real route. */
-       dplane_res = dplane_intf_addr_unset(ifp, ifc);
-       if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
-               vty_out(vty, "%% Can't unset interface IP address: %s.\n",
-                       dplane_res2str(dplane_res));
-               return CMD_WARNING_CONFIG_FAILED;
-       }
        UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
-       /* we will receive a kernel notification about this route being removed.
-        * this will trigger its removal from the connected list. */
-       return CMD_SUCCESS;
 }
 
-DEFUN (ip_address,
+#ifdef HAVE_NETLINK
+DEFPY_YANG (ip_address,
        ip_address_cmd,
-       "ip address A.B.C.D/M",
+       "[no] ip address A.B.C.D/M [label LINE$label]",
+       NO_STR
        "Interface Internet Protocol config commands\n"
        "Set the IP address of an interface\n"
-       "IP address (e.g. 10.0.0.1/8)\n")
-{
-       int idx_ipv4_prefixlen = 2;
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
-                                 NULL);
-}
-
-DEFUN (no_ip_address,
-       no_ip_address_cmd,
-       "no ip address A.B.C.D/M",
+       "IP address (e.g. 10.0.0.1/8)\n"
+       "Label of this address\n"
+       "Label\n")
+#else
+DEFPY_YANG (ip_address,
+       ip_address_cmd,
+       "[no] ip address A.B.C.D/M",
        NO_STR
        "Interface Internet Protocol config commands\n"
        "Set the IP address of an interface\n"
-       "IP Address (e.g. 10.0.0.1/8)\n")
+       "IP address (e.g. 10.0.0.1/8)\n")
+#endif
 {
-       int idx_ipv4_prefixlen = 3;
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
-                                   NULL, NULL);
+       char ip[INET_ADDRSTRLEN + 3];
+       char *mask;
+
+       if (no) {
+               nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+       } else {
+               nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+#ifdef HAVE_NETLINK
+               if (label)
+                       nb_cli_enqueue_change(vty, "./label", NB_OP_MODIFY,
+                                             label);
+               else
+                       nb_cli_enqueue_change(vty, "./label", NB_OP_DESTROY,
+                                             NULL);
+#endif
+       }
+
+       strlcpy(ip, address_str, sizeof(ip));
+
+       mask = strchr(ip, '/');
+       *mask = 0;
+       mask++;
+
+       return nb_cli_apply_changes(vty,
+                                   "./frr-zebra:zebra/ipv4-addrs[ip='%s'][prefix-length='%s']",
+                                   ip, mask);
 }
 
-DEFUN(ip_address_peer,
+#ifdef HAVE_NETLINK
+DEFPY_YANG (ip_address_peer,
       ip_address_peer_cmd,
-      "ip address A.B.C.D peer A.B.C.D/M",
+      "[no] ip address A.B.C.D peer A.B.C.D/M [label LINE$label]",
+      NO_STR
       "Interface Internet Protocol config commands\n"
       "Set the IP address of an interface\n"
       "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
       "Specify P-t-P address\n"
-      "Peer IP address (e.g. 10.0.0.1/8)\n")
-{
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL);
-}
-
-DEFUN(no_ip_address_peer,
-      no_ip_address_peer_cmd,
-      "no ip address A.B.C.D peer A.B.C.D/M",
+      "Peer IP address (e.g. 10.0.0.1/8)\n"
+      "Label of this address\n"
+      "Label\n")
+#else
+DEFPY_YANG (ip_address_peer,
+      ip_address_peer_cmd,
+      "[no] ip address A.B.C.D peer A.B.C.D/M",
       NO_STR
       "Interface Internet Protocol config commands\n"
       "Set the IP address of an interface\n"
       "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
       "Specify P-t-P address\n"
       "Peer IP address (e.g. 10.0.0.1/8)\n")
+#endif
 {
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL);
-}
+       char peer_ip[INET_ADDRSTRLEN + 3];
+       char *peer_mask;
 
+       if (no) {
+               nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+       } else {
+               nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
 #ifdef HAVE_NETLINK
-DEFUN (ip_address_label,
-       ip_address_label_cmd,
-       "ip address A.B.C.D/M label LINE",
-       "Interface Internet Protocol config commands\n"
-       "Set the IP address of an interface\n"
-       "IP address (e.g. 10.0.0.1/8)\n"
-       "Label of this address\n"
-       "Label\n")
-{
-       int idx_ipv4_prefixlen = 2;
-       int idx_line = 4;
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
-                                 argv[idx_line]->arg);
-}
-
-DEFUN (no_ip_address_label,
-       no_ip_address_label_cmd,
-       "no ip address A.B.C.D/M label LINE",
-       NO_STR
-       "Interface Internet Protocol config commands\n"
-       "Set the IP address of an interface\n"
-       "IP address (e.g. 10.0.0.1/8)\n"
-       "Label of this address\n"
-       "Label\n")
-{
-       int idx_ipv4_prefixlen = 3;
-       int idx_line = 5;
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
-                                   NULL, argv[idx_line]->arg);
-}
-#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. */
-               if_connected_add_tail(ifp->connected, ifc);
+                       nb_cli_enqueue_change(vty, "./label", NB_OP_MODIFY,
+                                             label);
+               else
+                       nb_cli_enqueue_change(vty, "./label", NB_OP_DESTROY,
+                                             NULL);
+#endif
        }
 
-       /* This address is configured from zebra. */
-       if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
-               SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
+       strlcpy(peer_ip, peer_str, sizeof(peer_ip));
 
-       /* 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_DATA_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.",
-                               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. */
-       }
+       peer_mask = strchr(peer_ip, '/');
+       *peer_mask = 0;
+       peer_mask++;
 
-       return 0;
+       return nb_cli_apply_changes(
+               vty,
+               "./frr-zebra:zebra/ipv4-p2p-addrs[ip='%s'][peer-ip='%s'][peer-prefix-length='%s']",
+               address_str, peer_ip, peer_mask);
 }
 
-static int ipv6_address_install(struct vty *vty, struct interface *ifp,
-                               const char *addr_str, const char *peer_str,
-                               const char *label)
+void if_ipv6_address_install(struct interface *ifp, struct prefix *prefix)
 {
        struct zebra_if *if_data;
-       struct prefix_ipv6 cp;
        struct connected *ifc;
-       struct prefix_ipv6 *p;
-       int ret;
-       enum zebra_dplane_result dplane_res;
 
        if_data = ifp->info;
 
-       ret = str2prefix_ipv6(addr_str, &cp);
-       if (ret <= 0) {
-               vty_out(vty, "%% Malformed address \n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (ipv6_martian(&cp.prefix)) {
-               vty_out(vty, "%% Invalid address\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       ifc = connected_check(ifp, (struct prefix *)&cp);
+       ifc = connected_check(ifp, prefix);
        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);
+               ifc->address = prefix_new();
+               prefix_copy(ifc->address, prefix);
 
                /* Add to linked list. */
                if_connected_add_tail(ifp->connected, ifc);
@@ -5218,48 +4946,21 @@ static int ipv6_address_install(struct vty *vty, struct interface *ifp,
                        if_refresh(ifp);
                }
 
-               dplane_res = dplane_intf_addr_set(ifp, ifc);
-               if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
-                       vty_out(vty, "%% Can't set interface IP address: %s.\n",
-                               dplane_res2str(dplane_res));
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
+               dplane_intf_addr_set(ifp, ifc);
 
                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 CMD_SUCCESS;
 }
 
-static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
-                                 const char *addr_str, const char *peer_str,
-                                 const char *label)
+void if_ipv6_address_uninstall(struct interface *ifp, struct prefix *prefix)
 {
-       struct prefix_ipv6 cp;
        struct connected *ifc;
-       int ret;
-       enum zebra_dplane_result dplane_res;
 
-       /* Convert to prefix structure. */
-       ret = str2prefix_ipv6(addr_str, &cp);
-       if (ret <= 0) {
-               vty_out(vty, "%% Malformed address \n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       /* Check current interface address. */
-       ifc = connected_check(ifp, (struct prefix *)&cp);
-       if (!ifc) {
-               vty_out(vty, "%% Can't find address\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       /* This is not configured address. */
-       if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
-               return CMD_WARNING_CONFIG_FAILED;
+       ifc = connected_check(ifp, prefix);
+       assert(ifc);
 
        UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
 
@@ -5268,48 +4969,40 @@ static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
            || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
                if_connected_del(ifp->connected, ifc);
                connected_free(&ifc);
-               return CMD_WARNING_CONFIG_FAILED;
+               return;
        }
 
        /* This is real route. */
-       dplane_res = dplane_intf_addr_unset(ifp, ifc);
-       if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
-               vty_out(vty, "%% Can't unset interface IP address: %s.\n",
-                       dplane_res2str(dplane_res));
-               return CMD_WARNING_CONFIG_FAILED;
-       }
+       dplane_intf_addr_unset(ifp, ifc);
 
        UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
-       /* This information will be propagated to the zclients when the
-        * kernel notification is received. */
-       return CMD_SUCCESS;
 }
 
-DEFUN (ipv6_address,
+DEFPY_YANG (ipv6_address,
        ipv6_address_cmd,
-       "ipv6 address X:X::X:X/M",
-       "Interface IPv6 config commands\n"
-       "Set the IP address of an interface\n"
-       "IPv6 address (e.g. 3ffe:506::1/48)\n")
-{
-       int idx_ipv6_prefixlen = 2;
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
-                                   NULL, NULL);
-}
-
-DEFUN (no_ipv6_address,
-       no_ipv6_address_cmd,
-       "no ipv6 address X:X::X:X/M",
+       "[no] ipv6 address X:X::X:X/M",
        NO_STR
        "Interface IPv6 config commands\n"
        "Set the IP address of an interface\n"
        "IPv6 address (e.g. 3ffe:506::1/48)\n")
 {
-       int idx_ipv6_prefixlen = 3;
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
-                                     NULL, NULL);
+       char ip[INET6_ADDRSTRLEN + 4];
+       char *mask;
+
+       if (no)
+               nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+       else
+               nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+
+       strlcpy(ip, address_str, sizeof(ip));
+
+       mask = strchr(ip, '/');
+       *mask = 0;
+       mask++;
+
+       return nb_cli_apply_changes(vty,
+                                   "./frr-zebra:zebra/ipv6-addrs[ip='%s'][prefix-length='%s']",
+                                   ip, mask);
 }
 
 static int link_params_config_write(struct vty *vty, struct interface *ifp)
@@ -5487,15 +5180,8 @@ void zebra_if_init(void)
        install_element(INTERFACE_NODE, &shutdown_if_cmd);
        install_element(INTERFACE_NODE, &bandwidth_if_cmd);
        install_element(INTERFACE_NODE, &ip_address_cmd);
-       install_element(INTERFACE_NODE, &no_ip_address_cmd);
        install_element(INTERFACE_NODE, &ip_address_peer_cmd);
-       install_element(INTERFACE_NODE, &no_ip_address_peer_cmd);
        install_element(INTERFACE_NODE, &ipv6_address_cmd);
-       install_element(INTERFACE_NODE, &no_ipv6_address_cmd);
-#ifdef HAVE_NETLINK
-       install_element(INTERFACE_NODE, &ip_address_label_cmd);
-       install_element(INTERFACE_NODE, &no_ip_address_label_cmd);
-#endif /* HAVE_NETLINK */
        install_element(INTERFACE_NODE, &link_params_cmd);
        install_default(LINK_PARAMS_NODE);
        install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
index a96f2ec7188d34bdb799f97ec02fa8f23378e3ef..0c9831b7da78c1e3eace2ac10d894ae53beb9ecf 100644 (file)
@@ -307,11 +307,14 @@ extern void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode,
  */
 extern int zebra_if_set_protodown(struct interface *ifp, bool down,
                                  enum protodown_reasons new_reason);
-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 void if_ip_address_install(struct interface *ifp, struct prefix *prefix,
+                                 const char *label, struct prefix *pp);
+extern void if_ip_address_uninstall(struct interface *ifp,
+                                   struct prefix *prefix, struct prefix *pp);
+extern void if_ipv6_address_install(struct interface *ifp,
+                                   struct prefix *prefix);
+extern void if_ipv6_address_uninstall(struct interface *ifp,
+                                     struct prefix *prefix);
 extern int if_shutdown(struct interface *ifp);
 extern int if_no_shutdown(struct interface *ifp);
 extern void if_arp(struct interface *ifp, bool enable);
index bf5650ce61fc2ee532d630860a6d432667b9204e..ddb2e8f3251576353f73d1cd0b0799d8d77e719a 100644 (file)
@@ -290,24 +290,38 @@ const struct frr_yang_module_info frr_zebra_info = {
                        }
                },
                {
-                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ip-addrs",
+                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs",
                        .cbs = {
-                               .create = lib_interface_zebra_ip_addrs_create,
-                               .destroy = lib_interface_zebra_ip_addrs_destroy,
+                               .create = lib_interface_zebra_ipv4_addrs_create,
+                               .destroy = lib_interface_zebra_ipv4_addrs_destroy,
                        }
                },
                {
-                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ip-addrs/label",
+                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs/label",
                        .cbs = {
-                               .modify = lib_interface_zebra_ip_addrs_label_modify,
-                               .destroy = lib_interface_zebra_ip_addrs_label_destroy,
+                               .modify = lib_interface_zebra_ipv4_addrs_label_modify,
+                               .destroy = lib_interface_zebra_ipv4_addrs_label_destroy,
                        }
                },
                {
-                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ip-addrs/ip4-peer",
+                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs",
                        .cbs = {
-                               .modify = lib_interface_zebra_ip_addrs_ip4_peer_modify,
-                               .destroy = lib_interface_zebra_ip_addrs_ip4_peer_destroy,
+                               .create = lib_interface_zebra_ipv4_p2p_addrs_create,
+                               .destroy = lib_interface_zebra_ipv4_p2p_addrs_destroy,
+                       }
+               },
+               {
+                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs/label",
+                       .cbs = {
+                               .modify = lib_interface_zebra_ipv4_p2p_addrs_label_modify,
+                               .destroy = lib_interface_zebra_ipv4_p2p_addrs_label_destroy,
+                       }
+               },
+               {
+                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-addrs",
+                       .cbs = {
+                               .create = lib_interface_zebra_ipv6_addrs_create,
+                               .destroy = lib_interface_zebra_ipv6_addrs_destroy,
                        }
                },
                {
index 92cabe30425b1e60d7e10addc5b6c88e5795ce10..13d42d41d237ceab7d29181ee4dbbd0de0a5baf0 100644 (file)
@@ -80,14 +80,18 @@ int zebra_debugs_debug_dplane_detail_modify(struct nb_cb_modify_args *args);
 int zebra_debugs_debug_dplane_detail_destroy(struct nb_cb_destroy_args *args);
 int zebra_debugs_debug_mlag_modify(struct nb_cb_modify_args *args);
 int zebra_debugs_debug_mlag_destroy(struct nb_cb_destroy_args *args);
-int lib_interface_zebra_ip_addrs_create(struct nb_cb_create_args *args);
-int lib_interface_zebra_ip_addrs_destroy(struct nb_cb_destroy_args *args);
-int lib_interface_zebra_ip_addrs_label_modify(struct nb_cb_modify_args *args);
-int lib_interface_zebra_ip_addrs_label_destroy(struct nb_cb_destroy_args *args);
-int lib_interface_zebra_ip_addrs_ip4_peer_modify(
+int lib_interface_zebra_ipv4_addrs_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv4_addrs_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv4_addrs_label_modify(struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv4_addrs_label_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv4_p2p_addrs_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv4_p2p_addrs_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv4_p2p_addrs_label_modify(
        struct nb_cb_modify_args *args);
-int lib_interface_zebra_ip_addrs_ip4_peer_destroy(
+int lib_interface_zebra_ipv4_p2p_addrs_label_destroy(
        struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_addrs_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv6_addrs_destroy(struct nb_cb_destroy_args *args);
 int lib_interface_zebra_multicast_modify(struct nb_cb_modify_args *args);
 int lib_interface_zebra_multicast_destroy(struct nb_cb_destroy_args *args);
 int lib_interface_zebra_link_detect_modify(struct nb_cb_modify_args *args);
index 8d27d321af97623b547cfefd533cc591605a6eaa..c704f79bca9629e871913084fc812516296136ee 100644 (file)
@@ -823,28 +823,26 @@ int zebra_debugs_debug_mlag_destroy(struct nb_cb_destroy_args *args)
 }
 
 /*
- * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ip-addrs
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs
  */
-int lib_interface_zebra_ip_addrs_create(struct nb_cb_create_args *args)
+int lib_interface_zebra_ipv4_addrs_create(struct nb_cb_create_args *args)
 {
        struct interface *ifp;
-       struct prefix prefix;
+       struct prefix p;
+       const char *label = NULL;
 
-       // addr_family = yang_dnode_get_enum(dnode, "address-family");
-       yang_dnode_get_prefix(&prefix, args->dnode, "ip-prefix");
-       apply_mask(&prefix);
+       p.family = AF_INET;
+       yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
+       p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
+
+       if (yang_dnode_exists(args->dnode, "label"))
+               label = yang_dnode_get_string(args->dnode, "label");
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               if (prefix.family == AF_INET
-                   && ipv4_martian(&prefix.u.prefix4)) {
-                       snprintfrr(args->errmsg, args->errmsg_len,
-                                  "invalid address %pFX", &prefix);
-                       return NB_ERR_VALIDATION;
-               } else if (prefix.family == AF_INET6
-                          && ipv6_martian(&prefix.u.prefix6)) {
+               if (ipv4_martian(&p.u.prefix4)) {
                        snprintfrr(args->errmsg, args->errmsg_len,
-                                  "invalid address %pFX", &prefix);
+                                  "invalid address %pFX", &p);
                        return NB_ERR_VALIDATION;
                }
                break;
@@ -853,65 +851,105 @@ int lib_interface_zebra_ip_addrs_create(struct nb_cb_create_args *args)
                break;
        case NB_EV_APPLY:
                ifp = nb_running_get_entry(args->dnode, NULL, true);
-               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);
+               if_ip_address_install(ifp, &p, label, NULL);
 
+               /* set something for checking on label modify */
+               nb_running_set_entry(args->dnode, (void *)0x1);
                break;
        }
 
        return NB_OK;
 }
 
-int lib_interface_zebra_ip_addrs_destroy(struct nb_cb_destroy_args *args)
+int lib_interface_zebra_ipv4_addrs_destroy(struct nb_cb_destroy_args *args)
 {
        struct interface *ifp;
-       struct prefix prefix;
-       struct connected *ifc;
+       struct prefix p;
 
-       yang_dnode_get_prefix(&prefix, args->dnode, "ip-prefix");
-       apply_mask(&prefix);
+       p.family = AF_INET;
+       yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
+       p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
 
        switch (args->event) {
        case NB_EV_VALIDATE:
+       case NB_EV_PREPARE:
+       case NB_EV_ABORT:
+               break;
+       case NB_EV_APPLY:
+               nb_running_unset_entry(args->dnode);
+
                ifp = nb_running_get_entry(args->dnode, NULL, false);
-               if (!ifp)
-                       return NB_OK;
+               if_ip_address_uninstall(ifp, &p, NULL);
+               break;
+       }
 
-               if (prefix.family == AF_INET) {
-                       /* Check current interface address. */
-                       ifc = connected_check_ptp(ifp, &prefix, NULL);
-                       if (!ifc) {
-                               snprintf(args->errmsg, args->errmsg_len,
-                                        "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) {
-                               snprintf(args->errmsg, args->errmsg_len,
-                                        "interface can't find address %s",
-                                        ifp->name);
-                               return NB_ERR_VALIDATION;
-                       }
-               } else
-                       return NB_ERR_VALIDATION;
+       return NB_OK;
+}
 
-               /* This is not configured address. */
-               if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) {
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs/label
+ */
+int lib_interface_zebra_ipv4_addrs_label_modify(struct nb_cb_modify_args *args)
+{
+       switch (args->event) {
+       case NB_EV_VALIDATE:
+               if (nb_running_get_entry_non_rec(lyd_parent(args->dnode), NULL,
+                                                false)) {
                        snprintf(args->errmsg, args->errmsg_len,
-                                "interface %s not configured", ifp->name);
+                                "Changing label is not allowed");
                        return NB_ERR_VALIDATION;
                }
+               break;
+       case NB_EV_PREPARE:
+       case NB_EV_ABORT:
+       case NB_EV_APPLY:
+               break;
+       }
+
+       return NB_OK;
+}
+
+int lib_interface_zebra_ipv4_addrs_label_destroy(struct nb_cb_destroy_args *args)
+{
+       switch (args->event) {
+       case NB_EV_VALIDATE:
+               snprintf(args->errmsg, args->errmsg_len,
+                        "Removing label is not allowed");
+               return NB_ERR_VALIDATION;
+       case NB_EV_PREPARE:
+       case NB_EV_ABORT:
+       case NB_EV_APPLY:
+               break;
+       }
+
+       return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs
+ */
+int lib_interface_zebra_ipv4_p2p_addrs_create(struct nb_cb_create_args *args)
+{
+       struct interface *ifp;
+       struct prefix p, pp;
+       const char *label = NULL;
+
+       p.family = AF_INET;
+       yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
+       p.prefixlen = 32;
+
+       pp.family = AF_INET;
+       yang_dnode_get_ipv4(&pp.u.prefix4, args->dnode, "peer-ip");
+       pp.prefixlen = yang_dnode_get_uint8(args->dnode, "peer-prefix-length");
 
-               /* 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)) {
-                       if_connected_del(ifp->connected, ifc);
-                       connected_free(&ifc);
+       if (yang_dnode_exists(args->dnode, "label"))
+               label = yang_dnode_get_string(args->dnode, "label");
+
+       switch (args->event) {
+       case NB_EV_VALIDATE:
+               if (ipv4_martian(&p.u.prefix4)) {
+                       snprintfrr(args->errmsg, args->errmsg_len,
+                                  "invalid address %pFX", &p);
                        return NB_ERR_VALIDATION;
                }
                break;
@@ -920,7 +958,39 @@ int lib_interface_zebra_ip_addrs_destroy(struct nb_cb_destroy_args *args)
                break;
        case NB_EV_APPLY:
                ifp = nb_running_get_entry(args->dnode, NULL, true);
-               if_ip_address_uinstall(ifp, &prefix);
+               if_ip_address_install(ifp, &p, label, &pp);
+
+               /* set something for checking on label modify */
+               nb_running_set_entry(args->dnode, (void *)0x1);
+               break;
+       }
+
+       return NB_OK;
+}
+
+int lib_interface_zebra_ipv4_p2p_addrs_destroy(struct nb_cb_destroy_args *args)
+{
+       struct interface *ifp;
+       struct prefix p, pp;
+
+       p.family = AF_INET;
+       yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
+       p.prefixlen = 32;
+
+       pp.family = AF_INET;
+       yang_dnode_get_ipv4(&pp.u.prefix4, args->dnode, "peer-ip");
+       pp.prefixlen = yang_dnode_get_uint8(args->dnode, "peer-prefix-length");
+
+       switch (args->event) {
+       case NB_EV_VALIDATE:
+       case NB_EV_PREPARE:
+       case NB_EV_ABORT:
+               break;
+       case NB_EV_APPLY:
+               nb_running_unset_entry(args->dnode);
+
+               ifp = nb_running_get_entry(args->dnode, NULL, false);
+               if_ip_address_uninstall(ifp, &p, &pp);
                break;
        }
 
@@ -928,30 +998,39 @@ int lib_interface_zebra_ip_addrs_destroy(struct nb_cb_destroy_args *args)
 }
 
 /*
- * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ip-addrs/label
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs/label
  */
-int lib_interface_zebra_ip_addrs_label_modify(struct nb_cb_modify_args *args)
+int lib_interface_zebra_ipv4_p2p_addrs_label_modify(struct nb_cb_modify_args *args)
 {
        switch (args->event) {
        case NB_EV_VALIDATE:
+               if (nb_running_get_entry_non_rec(lyd_parent(args->dnode), NULL,
+                                                false)) {
+                       snprintf(args->errmsg, args->errmsg_len,
+                                "Changing label is not allowed");
+                       return NB_ERR_VALIDATION;
+               }
+               break;
        case NB_EV_PREPARE:
        case NB_EV_ABORT:
        case NB_EV_APPLY:
-               /* TODO: implement me. */
                break;
        }
 
        return NB_OK;
 }
 
-int lib_interface_zebra_ip_addrs_label_destroy(struct nb_cb_destroy_args *args)
+int lib_interface_zebra_ipv4_p2p_addrs_label_destroy(
+       struct nb_cb_destroy_args *args)
 {
        switch (args->event) {
        case NB_EV_VALIDATE:
+               snprintf(args->errmsg, args->errmsg_len,
+                        "Removing label is not allowed");
+               return NB_ERR_VALIDATION;
        case NB_EV_PREPARE:
        case NB_EV_ABORT:
        case NB_EV_APPLY:
-               /* TODO: implement me. */
                break;
        }
 
@@ -959,31 +1038,54 @@ int lib_interface_zebra_ip_addrs_label_destroy(struct nb_cb_destroy_args *args)
 }
 
 /*
- * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ip-addrs/ip4-peer
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-addrs
  */
-int lib_interface_zebra_ip_addrs_ip4_peer_modify(struct nb_cb_modify_args *args)
+int lib_interface_zebra_ipv6_addrs_create(struct nb_cb_create_args *args)
 {
+       struct interface *ifp;
+       struct prefix p;
+
+       p.family = AF_INET6;
+       yang_dnode_get_ipv6(&p.u.prefix6, args->dnode, "ip");
+       p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
+
        switch (args->event) {
        case NB_EV_VALIDATE:
+               if (ipv6_martian(&p.u.prefix6)) {
+                       snprintfrr(args->errmsg, args->errmsg_len,
+                                  "invalid address %pFX", &p);
+                       return NB_ERR_VALIDATION;
+               }
+               break;
        case NB_EV_PREPARE:
        case NB_EV_ABORT:
+               break;
        case NB_EV_APPLY:
-               /* TODO: implement me. */
+               ifp = nb_running_get_entry(args->dnode, NULL, true);
+               if_ipv6_address_install(ifp, &p);
                break;
        }
 
        return NB_OK;
 }
 
-int lib_interface_zebra_ip_addrs_ip4_peer_destroy(
-       struct nb_cb_destroy_args *args)
+int lib_interface_zebra_ipv6_addrs_destroy(struct nb_cb_destroy_args *args)
 {
+       struct interface *ifp;
+       struct prefix p;
+
+       p.family = AF_INET6;
+       yang_dnode_get_ipv6(&p.u.prefix6, args->dnode, "ip");
+       p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
+
        switch (args->event) {
        case NB_EV_VALIDATE:
        case NB_EV_PREPARE:
        case NB_EV_ABORT:
+               break;
        case NB_EV_APPLY:
-               /* TODO: implement me. */
+               ifp = nb_running_get_entry(args->dnode, NULL, false);
+               if_ipv6_address_uninstall(ifp, &p);
                break;
        }