]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: convert interface ipv6 nd ra interval/lifetime commands to NB
authorIgor Ryzhov <iryzhov@nfware.com>
Tue, 23 Jan 2024 14:04:39 +0000 (16:04 +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/rtadv.c
zebra/rtadv.h
zebra/zebra_nb.c
zebra/zebra_nb.h
zebra/zebra_nb_config.c

index fd263406f34a40f88c203f8c664e61d5cdf4ec2b..054192bb1622bf688b1d3c492abf613f101df174 100644 (file)
@@ -2278,6 +2278,74 @@ module frr-zebra {
             "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
                        - AdvSendAdvertisements";
         }
+        leaf max-rtr-adv-interval {
+          type uint32 {
+            range "70..1800000";
+          }
+          units "milliseconds";
+          default "600000";
+          description
+            "The maximum time allowed between sending unsolicited
+            multicast Router Advertisements from the interface.";
+          reference
+            "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+                       - MaxRtrAdvInterval
+             RFC 6275: Mobility Support in IPv6";
+        }
+        // Setting this value is not yet supported by the actual code.
+        /*
+        leaf min-rtr-adv-interval {
+          type uint32 {
+            range "30..1350000";
+          }
+          units "milliseconds";
+          must ". <= 0.75 * ../max-rtr-adv-interval" {
+            description
+              "The value MUST NOT be greater than 75% of
+              'max-rtr-adv-interval'.";
+          }
+          description
+            "The minimum time allowed between sending unsolicited
+            multicast Router Advertisements from the interface.
+
+            The default value to be used operationally if this
+            leaf is not configured is determined as follows:
+
+            - if max-rtr-adv-interval >= 9 seconds, the default
+              value is 0.33 * max-rtr-adv-interval;
+
+            - otherwise, it is 0.75 * max-rtr-adv-interval.";
+          reference
+            "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+                       - MaxRtrAdvInterval
+             RFC 6275: Mobility Support in IPv6";
+        }
+        */
+        leaf default-lifetime {
+          type uint16 {
+            range "0..9000";
+          }
+          units "seconds";
+          must ". = 0 or . * 1000 >= ../max-rtr-adv-interval" {
+            description
+              "The value MUST NOT be less than max-rtr-adv-interval.";
+          }
+          description
+            "The value to be placed in the Router Lifetime field of
+            Router Advertisements sent from the interface, in
+            seconds.  It MUST be either zero or between
+            max-rtr-adv-interval and 9000 seconds.  A value of zero
+            indicates that the router is not to be used as a
+            default router.  These limits may be overridden by
+            specific documents that describe how IPv6 operates over
+            different link layers.
+
+            If this parameter is not configured, the device SHOULD
+            use a value of 3 * max-rtr-adv-interval.";
+          reference
+            "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+                       - AdvDefaultLifetime";
+        }
       }
       container state {
         config false;
index f6d3ec40d0cca32cd8ef3671de6cbeb5b8580e87..fb8ebae550205f3efe1f9f5a2d981bce925e1a8d 100644 (file)
@@ -1298,6 +1298,36 @@ void ipv6_nd_suppress_ra_set(struct interface *ifp,
        }
 }
 
+void ipv6_nd_interval_set(struct interface *ifp, uint32_t interval)
+{
+       struct zebra_if *zif = ifp->info;
+       struct zebra_vrf *zvrf = rtadv_interface_get_zvrf(ifp);
+       struct adv_if *adv_if;
+
+       if (zif->rtadv.MaxRtrAdvInterval % 1000) {
+               adv_if = adv_msec_if_del(zvrf, ifp->name);
+               if (adv_if != NULL)
+                       adv_if_free(adv_if);
+       }
+
+       if (interval % 1000)
+               (void)adv_msec_if_add(zvrf, ifp->name);
+
+       zif->rtadv.MaxRtrAdvInterval = interval;
+       zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
+
+       if (interval != RTADV_MAX_RTR_ADV_INTERVAL) {
+               SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
+               zif->rtadv.AdvIntervalTimer = 0;
+       } else {
+               if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
+                       zif->rtadv.MaxRtrAdvInterval = 10000;
+
+               UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
+               zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
+       }
+}
+
 /*
  * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
  * Note that while the client could request RA on an interface on which the
@@ -1652,173 +1682,54 @@ DEFPY_YANG (ipv6_nd_suppress_ra,
        return nb_cli_apply_changes(vty, NULL);
 }
 
-DEFUN (ipv6_nd_ra_interval_msec,
-       ipv6_nd_ra_interval_msec_cmd,
-       "ipv6 nd ra-interval msec (70-1800000)",
-       "Interface IPv6 config commands\n"
-       "Neighbor discovery\n"
-       "Router Advertisement interval\n"
-       "Router Advertisement interval in milliseconds\n"
-       "Router Advertisement interval in milliseconds\n")
-{
-       int idx_number = 4;
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       unsigned interval;
-       struct zebra_if *zif = ifp->info;
-       struct zebra_vrf *zvrf;
-       struct adv_if *adv_if;
-
-       zvrf = rtadv_interface_get_zvrf(ifp);
-
-       interval = strtoul(argv[idx_number]->arg, NULL, 10);
-       if ((zif->rtadv.AdvDefaultLifetime != -1
-            && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
-               vty_out(vty,
-                       "This ra-interval would conflict with configured ra-lifetime!\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (zif->rtadv.MaxRtrAdvInterval % 1000) {
-               adv_if = adv_msec_if_del(zvrf, ifp->name);
-               if (adv_if != NULL)
-                       adv_if_free(adv_if);
-       }
-
-       if (interval % 1000)
-               (void)adv_msec_if_add(zvrf, ifp->name);
-
-       SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
-       zif->rtadv.MaxRtrAdvInterval = interval;
-       zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
-       zif->rtadv.AdvIntervalTimer = 0;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_ra_interval,
+DEFPY_YANG (ipv6_nd_ra_interval,
        ipv6_nd_ra_interval_cmd,
-       "ipv6 nd ra-interval (1-1800)",
-       "Interface IPv6 config commands\n"
-       "Neighbor discovery\n"
-       "Router Advertisement interval\n"
-       "Router Advertisement interval in seconds\n")
-{
-       int idx_number = 3;
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       unsigned interval;
-       struct zebra_if *zif = ifp->info;
-       struct zebra_vrf *zvrf;
-       struct adv_if *adv_if;
-
-       zvrf = rtadv_interface_get_zvrf(ifp);
-
-       interval = strtoul(argv[idx_number]->arg, NULL, 10);
-       if ((zif->rtadv.AdvDefaultLifetime != -1
-            && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
-               vty_out(vty,
-                       "This ra-interval would conflict with configured ra-lifetime!\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (zif->rtadv.MaxRtrAdvInterval % 1000) {
-               adv_if = adv_msec_if_del(zvrf, ifp->name);
-               if (adv_if != NULL)
-                       adv_if_free(adv_if);
-       }
-
-       /* convert to milliseconds */
-       interval = interval * 1000;
-
-       SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
-       zif->rtadv.MaxRtrAdvInterval = interval;
-       zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
-       zif->rtadv.AdvIntervalTimer = 0;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_ra_interval,
-       no_ipv6_nd_ra_interval_cmd,
-       "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
+       "[no] ipv6 nd ra-interval ![<(1-1800)$sec|msec (70-1800000)$msec>]",
        NO_STR
        "Interface IPv6 config commands\n"
        "Neighbor discovery\n"
        "Router Advertisement interval\n"
        "Router Advertisement interval in seconds\n"
-       "Specify millisecond router advertisement interval\n"
+       "Router Advertisement interval in milliseconds\n"
        "Router Advertisement interval in milliseconds\n")
 {
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zif = ifp->info;
-       struct zebra_vrf *zvrf = NULL;
-       struct adv_if *adv_if;
+       char value[YANG_VALUE_MAXLEN];
 
-       zvrf = rtadv_interface_get_zvrf(ifp);
+       if (!no) {
+               if (sec)
+                       snprintf(value, sizeof(value), "%lu", sec * 1000);
+               else
+                       snprintf(value, sizeof(value), "%lu", msec);
 
-       if (zif->rtadv.MaxRtrAdvInterval % 1000) {
-               adv_if = adv_msec_if_del(zvrf, ifp->name);
-               if (adv_if != NULL)
-                       adv_if_free(adv_if);
+               nb_cli_enqueue_change(vty,
+                                     "./frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval",
+                                     NB_OP_MODIFY, value);
+       } else {
+               nb_cli_enqueue_change(vty,
+                                     "./frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval",
+                                     NB_OP_DESTROY, NULL);
        }
-
-       UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
-
-       if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
-               zif->rtadv.MaxRtrAdvInterval = 10000;
-       else
-               zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
-
-       zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
-       zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
-
-       return CMD_SUCCESS;
+       return nb_cli_apply_changes(vty, NULL);
 }
 
-DEFUN (ipv6_nd_ra_lifetime,
+DEFPY_YANG (ipv6_nd_ra_lifetime,
        ipv6_nd_ra_lifetime_cmd,
-       "ipv6 nd ra-lifetime (0-9000)",
-       "Interface IPv6 config commands\n"
-       "Neighbor discovery\n"
-       "Router lifetime\n"
-       "Router lifetime in seconds (0 stands for a non-default gw)\n")
-{
-       int idx_number = 3;
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zif = ifp->info;
-       int lifetime;
-
-       lifetime = strtoul(argv[idx_number]->arg, NULL, 10);
-
-       /* The value to be placed in the Router Lifetime field
-        * of Router Advertisements sent from the interface,
-        * in seconds.  MUST be either zero or between
-        * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
-       if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) {
-               vty_out(vty,
-                       "This ra-lifetime would conflict with configured ra-interval\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       zif->rtadv.AdvDefaultLifetime = lifetime;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_ra_lifetime,
-       no_ipv6_nd_ra_lifetime_cmd,
-       "no ipv6 nd ra-lifetime [(0-9000)]",
+       "[no] ipv6 nd ra-lifetime ![(0-9000)$lifetime]",
        NO_STR
        "Interface IPv6 config commands\n"
        "Neighbor discovery\n"
        "Router lifetime\n"
        "Router lifetime in seconds (0 stands for a non-default gw)\n")
 {
-       VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zif = ifp->info;
-
-       zif->rtadv.AdvDefaultLifetime = -1;
-
-       return CMD_SUCCESS;
+       if (!no)
+               nb_cli_enqueue_change(vty,
+                                     "./frr-zebra:zebra/ipv6-router-advertisements/default-lifetime",
+                                     NB_OP_MODIFY, lifetime_str);
+       else
+               nb_cli_enqueue_change(vty,
+                                     "./frr-zebra:zebra/ipv6-router-advertisements/default-lifetime",
+                                     NB_OP_DESTROY, NULL);
+       return nb_cli_apply_changes(vty, NULL);
 }
 
 DEFUN (ipv6_nd_reachable_time,
@@ -2904,10 +2815,7 @@ void rtadv_cmd_init(void)
        install_element(INTERFACE_NODE, &no_ipv6_nd_ra_hop_limit_cmd);
        install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
        install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
-       install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
-       install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
        install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
-       install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
        install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
        install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
        install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
index 79abe5f7e0750103cd3e6909d0d6148dcb1894a8..14a54435b0fd4c3fdaf8e502f2ba9257eaa770f3 100644 (file)
@@ -387,6 +387,7 @@ extern void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p);
 
 void ipv6_nd_suppress_ra_set(struct interface *ifp,
                             enum ipv6_nd_suppress_ra_status status);
+void ipv6_nd_interval_set(struct interface *ifp, uint32_t interval);
 
 #else /* !HAVE_RTADV */
 struct rtadv {
index 87cfab5469474f304d03b9bd01c13e870a2fcaf8..82aebda8ae8339db044726c65b6b886f65c83cef 100644 (file)
@@ -552,6 +552,19 @@ const struct frr_yang_module_info frr_zebra_info = {
                                .modify = lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify,
                        }
                },
+               {
+                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval",
+                       .cbs = {
+                               .modify = lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_modify,
+                       }
+               },
+               {
+                       .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-lifetime",
+                       .cbs = {
+                               .modify = lib_interface_zebra_ipv6_router_advertisements_default_lifetime_modify,
+                               .destroy = lib_interface_zebra_ipv6_router_advertisements_default_lifetime_destroy,
+                       }
+               },
                {
                        .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/state/up-count",
                        .cbs = {
index f45270f7b4fab94b71a308ce85f7ab12b458192d..a7b6797b6379278f8c334737977e9b71ff12dff7 100644 (file)
@@ -183,6 +183,12 @@ int lib_interface_zebra_evpn_mh_bypass_modify(struct nb_cb_modify_args *args);
 int lib_interface_zebra_evpn_mh_uplink_modify(struct nb_cb_modify_args *args);
 int lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify(
        struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_modify(
+       struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_modify(
+       struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_destroy(
+       struct nb_cb_destroy_args *args);
 struct yang_data *
 lib_interface_zebra_state_up_count_get_elem(struct nb_cb_get_elem_args *args);
 struct yang_data *
index d13a75866f54d5a80d44056b0e62b438c8032f14..f0d4faaf840ad8b0e1463f4788d88df4c0806635 100644 (file)
@@ -2485,6 +2485,66 @@ int lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify(
        return NB_OK;
 }
 
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval
+ */
+int lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_modify(
+       struct nb_cb_modify_args *args)
+{
+       struct interface *ifp;
+       uint32_t interval;
+
+       if (args->event != NB_EV_APPLY)
+               return NB_OK;
+
+       ifp = nb_running_get_entry(args->dnode, NULL, true);
+       interval = yang_dnode_get_uint32(args->dnode, NULL);
+
+       ipv6_nd_interval_set(ifp, interval);
+
+       return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-lifetime
+ */
+int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_modify(
+       struct nb_cb_modify_args *args)
+{
+       struct interface *ifp;
+       struct zebra_if *zif;
+       uint16_t lifetime;
+
+       if (args->event != NB_EV_APPLY)
+               return NB_OK;
+
+       ifp = nb_running_get_entry(args->dnode, NULL, true);
+       zif = ifp->info;
+
+       lifetime = yang_dnode_get_uint16(args->dnode, NULL);
+
+       zif->rtadv.AdvDefaultLifetime = lifetime;
+
+       return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_destroy(
+       struct nb_cb_destroy_args *args)
+{
+       struct interface *ifp;
+       struct zebra_if *zif;
+
+       if (args->event != NB_EV_APPLY)
+               return NB_OK;
+
+       ifp = nb_running_get_entry(args->dnode, NULL, true);
+       zif = ifp->info;
+
+       zif->rtadv.AdvDefaultLifetime = -1;
+
+       return NB_OK;
+}
+
 /*
  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
  */