"RFC 4191: Default Router Preferences and More-Specific
Routes";
}
+ container prefix-list {
+ description
+ "Support for prefixes to be placed in Prefix
+ Information options in Router Advertisement messages
+ sent from the interface.
+
+ Prefixes that are advertised by default but do not
+ have their entries in the child 'prefix' list are
+ advertised with the default values of all parameters.
+
+ The link-local prefix SHOULD NOT be included in the
+ list of advertised prefixes.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ - AdvPrefixList";
+ list prefix {
+ key "prefix-spec";
+ description
+ "Support for an advertised prefix entry.";
+ leaf prefix-spec {
+ type inet:ipv6-prefix;
+ description
+ "IPv6 address prefix.";
+ }
+ // FRR doesn't support 'no-advertise'. Keeping the code
+ // here for future reference.
+ /*
+ choice control-adv-prefixes {
+ default "advertise";
+ description
+ "Either (1) the prefix is explicitly removed from the
+ set of advertised prefixes or (2) the parameters with
+ which the prefix is advertised are specified (default
+ case).";
+ leaf no-advertise {
+ type empty;
+ description
+ "The prefix will not be advertised.
+
+ This can be used for removing the prefix from
+ the default set of advertised prefixes.";
+ }
+ case advertise {
+ */
+ leaf valid-lifetime {
+ type uint32;
+ units "seconds";
+ default "2592000";
+ description
+ "The value to be placed in the Valid Lifetime
+ in the Prefix Information option. The
+ designated value of all 1's (0xffffffff)
+ represents infinity.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6
+ (IPv6) - AdvValidLifetime";
+ }
+ leaf on-link-flag {
+ type boolean;
+ default "true";
+ description
+ "The value to be placed in the on-link flag
+ ('L-bit') field in the Prefix Information
+ option.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6
+ (IPv6) - AdvOnLinkFlag";
+ }
+ leaf preferred-lifetime {
+ type uint32;
+ units "seconds";
+ must ". <= ../valid-lifetime" {
+ description
+ "This value MUST NOT be greater than
+ valid-lifetime.";
+ }
+ default "604800";
+ description
+ "The value to be placed in the Preferred
+ Lifetime in the Prefix Information option.
+ The designated value of all 1's (0xffffffff)
+ represents infinity.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6
+ (IPv6) - AdvPreferredLifetime";
+ }
+ leaf autonomous-flag {
+ type boolean;
+ default "true";
+ description
+ "The value to be placed in the Autonomous Flag
+ field in the Prefix Information option.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6
+ (IPv6) - AdvAutonomousFlag";
+ }
+ leaf router-address-flag {
+ type boolean;
+ default "false";
+ description
+ "The value to be placed in the Router Address
+ flag field in the Prefix Information option.";
+ reference
+ "RFC 6275: Mobility Support in IPv6";
+ }
+ /*
+ }
+ }
+ */
+ // This is closing brackets for `case advertise` and
+ // `choice control-adv-prefixes`.
+ }
+ }
}
container state {
config false;
rp->AdvValidLifetime = RTADV_VALID_LIFETIME;
}
-static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
+static struct rtadv_prefix *rtadv_prefix_set(struct zebra_if *zif,
+ struct rtadv_prefix *rp)
{
struct rtadv_prefix *rprefix;
rtadv_prefix_set_defaults(rprefix);
}
}
+
+ return rprefix;
}
-static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
+static void rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp,
+ struct rtadv_prefix *rprefix)
{
- struct rtadv_prefix *rprefix;
+ if (!rprefix)
+ rprefix = rtadv_prefixes_find(zif->rtadv.prefixes, rp);
- rprefix = rtadv_prefixes_find(zif->rtadv.prefixes, rp);
if (rprefix != NULL) {
/*
if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
rtadv_prefix_set_defaults(rprefix);
- return 1;
+ return;
}
} else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
- return 1;
+ return;
}
}
rtadv_prefixes_del(zif->rtadv.prefixes, rprefix);
rtadv_prefix_free(rprefix);
- return 1;
- } else
- return 0;
+ }
+}
+
+struct rtadv_prefix *rtadv_add_prefix_manual(struct zebra_if *zif,
+ struct rtadv_prefix *rp)
+{
+ rp->AdvPrefixCreate = PREFIX_SRC_MANUAL;
+ return rtadv_prefix_set(zif, rp);
+}
+
+void rtadv_delete_prefix_manual(struct zebra_if *zif,
+ struct rtadv_prefix *rprefix)
+{
+ struct rtadv_prefix rp;
+
+ rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
+
+ rtadv_prefix_reset(zif, &rp, rprefix);
}
/* Add IPv6 prefixes learned from the kernel to the RA prefix list */
rp.prefix = *((struct prefix_ipv6 *)p);
apply_mask_ipv6(&rp.prefix);
rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
- rtadv_prefix_reset(zif, &rp);
+ rtadv_prefix_reset(zif, &rp, NULL);
}
static void rtadv_start_interface_events(struct zebra_vrf *zvrf,
frr_each_safe (rtadv_prefixes, zif->rtadv.prefixes,
rprefix)
- rtadv_prefix_reset(zif, rprefix);
+ rtadv_prefix_reset(zif, rprefix, rprefix);
rtadv_stop_ra(ifp);
}
return nb_cli_apply_changes(vty, NULL);
}
-DEFUN (ipv6_nd_prefix,
+DEFPY_YANG (ipv6_nd_prefix,
ipv6_nd_prefix_cmd,
- "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
+ "[no] ipv6 nd prefix X:X::X:X/M$prefix [<(0-4294967295)|infinite>$valid <(0-4294967295)|infinite>$preferred] [{router-address$routeraddr|off-link$offlink|no-autoconfig$noautoconf}]",
+ NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Prefix information\n"
"Infinite preferred lifetime\n"
"Set Router Address flag\n"
"Do not use prefix for onlink determination\n"
- "Do not use prefix for autoconfiguration\n"
- "Do not use prefix for autoconfiguration\n"
- "Do not use prefix for onlink determination\n")
-{
- /* prelude */
- char *prefix = argv[3]->arg;
- int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
- || strmatch(argv[4]->text, "infinite"));
- int routeropts = lifetimes ? argc > 6 : argc > 4;
-
- int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
-
- char *lifetime = NULL, *preflifetime = NULL;
- int routeraddr = 0, offlink = 0, noautoconf = 0;
- if (lifetimes) {
- lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
- : argv[4]->text;
- preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg
- : argv[5]->text;
- }
- if (routeropts) {
- routeraddr =
- strmatch(argv[idx_routeropts]->text, "router-address");
- if (!routeraddr) {
- offlink = (argc > idx_routeropts + 1
- || strmatch(argv[idx_routeropts]->text,
- "off-link"));
- noautoconf = (argc > idx_routeropts + 1
- || strmatch(argv[idx_routeropts]->text,
- "no-autoconfig"));
+ "Do not use prefix for autoconfiguration\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ if (valid) {
+ if (strmatch(valid, "infinite"))
+ valid = "4294967295";
+ nb_cli_enqueue_change(vty, "./valid-lifetime",
+ NB_OP_MODIFY, valid);
+ } else {
+ nb_cli_enqueue_change(vty, "./valid-lifetime",
+ NB_OP_DESTROY, NULL);
}
- }
-
- /* business */
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zebra_if = ifp->info;
- int ret;
- struct rtadv_prefix rp;
-
- ret = str2prefix_ipv6(prefix, &rp.prefix);
- if (!ret) {
- vty_out(vty, "Malformed IPv6 prefix\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
- rp.AdvOnLinkFlag = !offlink;
- rp.AdvAutonomousFlag = !noautoconf;
- rp.AdvRouterAddressFlag = routeraddr;
- rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
- rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
- rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
-
- if (lifetimes) {
- rp.AdvValidLifetime = strmatch(lifetime, "infinite")
- ? UINT32_MAX
- : strtoll(lifetime, NULL, 10);
- rp.AdvPreferredLifetime =
- strmatch(preflifetime, "infinite")
- ? UINT32_MAX
- : strtoll(preflifetime, NULL, 10);
- if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) {
- vty_out(vty, "Invalid preferred lifetime\n");
- return CMD_WARNING_CONFIG_FAILED;
+ if (preferred) {
+ if (strmatch(preferred, "infinite"))
+ preferred = "4294967295";
+ nb_cli_enqueue_change(vty, "./preferred-lifetime",
+ NB_OP_MODIFY, preferred);
+ } else {
+ nb_cli_enqueue_change(vty, "./preferred-lifetime",
+ NB_OP_DESTROY, NULL);
}
+ if (routeraddr)
+ nb_cli_enqueue_change(vty, "./router-address-flag",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty, "./router-address-flag",
+ NB_OP_DESTROY, NULL);
+ if (offlink)
+ nb_cli_enqueue_change(vty, "./on-link-flag",
+ NB_OP_MODIFY, "false");
+ else
+ nb_cli_enqueue_change(vty, "./on-link-flag",
+ NB_OP_DESTROY, NULL);
+ if (noautoconf)
+ nb_cli_enqueue_change(vty, "./autonomous-flag",
+ NB_OP_MODIFY, "false");
+ else
+ nb_cli_enqueue_change(vty, "./autonomous-flag",
+ NB_OP_DESTROY, NULL);
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
}
-
- rtadv_prefix_set(zebra_if, &rp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_prefix,
- no_ipv6_nd_prefix_cmd,
- "no ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n"
- "Preferred lifetime in seconds\n"
- "Infinite preferred lifetime\n"
- "Set Router Address flag\n"
- "Do not use prefix for onlink determination\n"
- "Do not use prefix for autoconfiguration\n"
- "Do not use prefix for autoconfiguration\n"
- "Do not use prefix for onlink determination\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zebra_if = ifp->info;
- int ret;
- struct rtadv_prefix rp;
- char *prefix = argv[4]->arg;
-
- ret = str2prefix_ipv6(prefix, &rp.prefix);
- if (!ret) {
- vty_out(vty, "Malformed IPv6 prefix\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
- rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
-
- ret = rtadv_prefix_reset(zebra_if, &rp);
- if (!ret) {
- vty_out(vty, "Non-existant IPv6 prefix\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(
+ vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix[prefix-spec='%s']",
+ prefix_str);
}
DEFPY_YANG (ipv6_nd_router_preference,
install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_rdnss_cmd);
extern void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p);
extern void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p);
+/* returns created prefix */
+struct rtadv_prefix *rtadv_add_prefix_manual(struct zebra_if *zif,
+ struct rtadv_prefix *rp);
+/* rprefix must be the one returned by rtadv_add_prefix_manual */
+void rtadv_delete_prefix_manual(struct zebra_if *zif,
+ struct rtadv_prefix *rprefix);
+
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);
.modify = lib_interface_zebra_ipv6_router_advertisements_default_router_preference_modify,
}
},
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix",
+ .cbs = {
+ .create = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_create,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/valid-lifetime",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_valid_lifetime_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/on-link-flag",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_on_link_flag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/preferred-lifetime",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_preferred_lifetime_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/autonomous-flag",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_autonomous_flag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/router-address-flag",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_router_address_flag_modify,
+ }
+ },
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/state/up-count",
.cbs = {
struct nb_cb_destroy_args *args);
int lib_interface_zebra_ipv6_router_advertisements_default_router_preference_modify(
struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_create(
+ struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_valid_lifetime_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_on_link_flag_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_preferred_lifetime_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_autonomous_flag_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_router_address_flag_modify(
+ struct nb_cb_modify_args *args);
struct yang_data *
lib_interface_zebra_state_up_count_get_elem(struct nb_cb_get_elem_args *args);
struct yang_data *
return NB_OK;
}
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_create(
+ struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ struct rtadv_prefix rp, *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ yang_dnode_get_ipv6p(&rp.prefix, args->dnode, "prefix-spec");
+ rp.AdvOnLinkFlag = !!yang_dnode_get_bool(args->dnode, "on-link-flag");
+ rp.AdvAutonomousFlag = !!yang_dnode_get_bool(args->dnode,
+ "autonomous-flag");
+ rp.AdvRouterAddressFlag = !!yang_dnode_get_bool(args->dnode,
+ "router-address-flag");
+ rp.AdvValidLifetime = yang_dnode_get_uint32(args->dnode,
+ "valid-lifetime");
+ rp.AdvPreferredLifetime = yang_dnode_get_uint32(args->dnode,
+ "preferred-lifetime");
+
+ prefix = rtadv_add_prefix_manual(ifp->info, &rp);
+ nb_running_set_entry(args->dnode, prefix);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_unset_entry(args->dnode);
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ rtadv_delete_prefix_manual(ifp->info, prefix);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/valid-lifetime
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_valid_lifetime_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvValidLifetime = yang_dnode_get_uint32(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/on-link-flag
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_on_link_flag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvOnLinkFlag = !!yang_dnode_get_bool(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/preferred-lifetime
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_preferred_lifetime_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvPreferredLifetime = yang_dnode_get_uint32(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/autonomous-flag
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_autonomous_flag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvAutonomousFlag = !!yang_dnode_get_bool(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/router-address-flag
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_router_address_flag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvRouterAddressFlag = !!yang_dnode_get_bool(args->dnode, NULL);
+
+ return NB_OK;
+}
+
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
*/