diff options
| author | Donald Sharp <sharpd@cumulusnetworks.com> | 2020-08-10 08:39:51 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-10 08:39:51 -0400 | 
| commit | 8e3ac40d2cb5f38a2804d1b19eeb77aeebd7c7af (patch) | |
| tree | b543b31173d45d711fd229c83c50767e764f2494 | |
| parent | 84a98cedfb3efac93aef1058730bf1e6ca585fcc (diff) | |
| parent | 98a3fb0ab9b92443c0c92e073d3f184b88dcbfc6 (diff) | |
Merge pull request #6483 from sylane/router-id-v6
zebra: add IPv6 router-id
| -rw-r--r-- | doc/user/zebra.rst | 27 | ||||
| -rw-r--r-- | lib/zclient.c | 18 | ||||
| -rw-r--r-- | lib/zclient.h | 3 | ||||
| -rw-r--r-- | zebra/router-id.c | 439 | ||||
| -rw-r--r-- | zebra/router-id.h | 2 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 47 | ||||
| -rw-r--r-- | zebra/zapi_msg.h | 4 | ||||
| -rw-r--r-- | zebra/zebra_vrf.h | 5 | ||||
| -rw-r--r-- | zebra/zserv.c | 4 | ||||
| -rw-r--r-- | zebra/zserv.h | 2 | 
10 files changed, 435 insertions, 116 deletions
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 7b028fd674..a9ab162b40 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -1050,23 +1050,34 @@ Many routing protocols require a router-id to be configured. To have a  consistent router-id across all daemons, the following commands are available  to configure and display the router-id: -.. index:: [no] router-id A.B.C.D -.. clicmd:: [no] router-id A.B.C.D +.. index:: [no] [ip] router-id A.B.C.D +.. clicmd:: [no] [ip] router-id A.B.C.D     Allow entering of the router-id.  This command also works under the -   vrf subnode, to allow router-id's per vrf.  +   vrf subnode, to allow router-id's per vrf. -.. index:: [no] router-id A.B.C.D vrf NAME -.. clicmd:: [no] router-id A.B.C.D vrf NAME +.. index:: [no] [ip] router-id A.B.C.D vrf NAME +.. clicmd:: [no] [ip] router-id A.B.C.D vrf NAME     Configure the router-id of this router from the configure NODE.     A show run of this command will display the router-id command     under the vrf sub node.  This command is deprecated and will     be removed at some point in time in the future. -  -.. index:: show router-id [vrf NAME] -.. clicmd:: show router-id [vrf NAME] + +.. index:: show [ip] router-id [vrf NAME] +.. clicmd:: show [ip] router-id [vrf NAME]     Display the user configured router-id. +For protocols requiring an IPv6 router-id, the following commands are available: + +.. index:: [no] ipv6 router-id X:X::X:X +.. clicmd:: [no] ipv6 router-id X:X::X:X + +   Configure the IPv6 router-id of this router. Like its IPv4 counterpart, +   this command works under the vrf subnode, to allow router-id's per vrf. + +.. index:: show ipv6 router-id [vrf NAME] +.. clicmd:: show ipv6 router-id [vrf NAME] +   Display the user configured IPv6 router-id. diff --git a/lib/zclient.c b/lib/zclient.c index eb62350f4f..250d697bb4 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -436,7 +436,8 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)  			   vrf_id);  	/* We need router-id information. */ -	zebra_message_send(zclient, ZEBRA_ROUTER_ID_ADD, vrf_id); +	zclient_send_router_id_update(zclient, ZEBRA_ROUTER_ID_ADD, AFI_IP, +				      vrf_id);  	/* We need interface information. */  	zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, vrf_id); @@ -503,7 +504,8 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)  			   vrf_id);  	/* We need router-id information. */ -	zebra_message_send(zclient, ZEBRA_ROUTER_ID_DELETE, vrf_id); +	zclient_send_router_id_update(zclient, ZEBRA_ROUTER_ID_DELETE, AFI_IP, +				      vrf_id);  	zebra_message_send(zclient, ZEBRA_INTERFACE_DELETE, vrf_id); @@ -554,6 +556,18 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)  	}  } +int zclient_send_router_id_update(struct zclient *zclient, +				  zebra_message_types_t type, afi_t afi, +				  vrf_id_t vrf_id) +{ +	struct stream *s = zclient->obuf; +	stream_reset(s); +	zclient_create_header(s, type, vrf_id); +	stream_putw(s, afi); +	stream_putw_at(s, 0, stream_get_endp(s)); +	return zclient_send_message(zclient); +} +  /* Send request to zebra daemon to start or stop RA. */  void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,  				     struct interface *ifp, int enable, diff --git a/lib/zclient.h b/lib/zclient.h index da06239d01..f1730f15b2 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -659,6 +659,9 @@ extern void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id,  extern void zclient_send_reg_requests(struct zclient *, vrf_id_t);  extern void zclient_send_dereg_requests(struct zclient *, vrf_id_t); +extern int zclient_send_router_id_update(struct zclient *zclient, +					 zebra_message_types_t type, afi_t afi, +					 vrf_id_t vrf_id);  extern void zclient_send_interface_radv_req(struct zclient *zclient,  					    vrf_id_t vrf_id, diff --git a/zebra/router-id.c b/zebra/router-id.c index ba9e721614..7e81f29827 100644 --- a/zebra/router-id.c +++ b/zebra/router-id.c @@ -59,9 +59,6 @@ static struct connected *router_id_find_node(struct list *l,  static int router_id_bad_address(struct connected *ifc)  { -	if (ifc->address->family != AF_INET) -		return 1; -  	/* non-redistributable addresses shouldn't be used for RIDs either */  	if (!zebra_check_addr(ifc->address))  		return 1; @@ -69,40 +66,82 @@ static int router_id_bad_address(struct connected *ifc)  	return 0;  } -void router_id_get(struct prefix *p, struct zebra_vrf *zvrf) +static bool router_id_v6_is_any(struct prefix *p) +{ +	return memcmp(&p->u.prefix6, &in6addr_any, sizeof(struct in6_addr)) +	       == 0; +} + +int router_id_get(afi_t afi, struct prefix *p, struct zebra_vrf *zvrf)  {  	struct listnode *node;  	struct connected *c; - -	p->u.prefix4.s_addr = INADDR_ANY; -	p->family = AF_INET; -	p->prefixlen = 32; - -	if (zvrf->rid_user_assigned.u.prefix4.s_addr != INADDR_ANY) -		p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr; -	else if (!list_isempty(zvrf->rid_lo_sorted_list)) { -		node = listtail(zvrf->rid_lo_sorted_list); -		c = listgetdata(node); -		p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; -	} else if (!list_isempty(zvrf->rid_all_sorted_list)) { -		node = listtail(zvrf->rid_all_sorted_list); -		c = listgetdata(node); -		p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; +	struct in6_addr *addr = NULL; + +	switch (afi) { +	case AFI_IP: +		p->u.prefix4.s_addr = INADDR_ANY; +		p->family = AF_INET; +		p->prefixlen = 32; +		if (zvrf->rid_user_assigned.u.prefix4.s_addr != INADDR_ANY) +			p->u.prefix4.s_addr = +				zvrf->rid_user_assigned.u.prefix4.s_addr; +		else if (!list_isempty(zvrf->rid_lo_sorted_list)) { +			node = listtail(zvrf->rid_lo_sorted_list); +			c = listgetdata(node); +			p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; +		} else if (!list_isempty(zvrf->rid_all_sorted_list)) { +			node = listtail(zvrf->rid_all_sorted_list); +			c = listgetdata(node); +			p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; +		} +		return 0; +	case AFI_IP6: +		p->u.prefix6 = in6addr_any; +		p->family = AF_INET6; +		p->prefixlen = 128; +		if (!router_id_v6_is_any(&zvrf->rid6_user_assigned)) +			addr = &zvrf->rid6_user_assigned.u.prefix6; +		else if (!list_isempty(zvrf->rid6_lo_sorted_list)) { +			node = listtail(zvrf->rid6_lo_sorted_list); +			c = listgetdata(node); +			addr = &c->address->u.prefix6; +		} else if (!list_isempty(zvrf->rid6_all_sorted_list)) { +			node = listtail(zvrf->rid6_all_sorted_list); +			c = listgetdata(node); +			addr = &c->address->u.prefix6; +		} +		if (addr) +			memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr)); +		return 0; +	default: +		return -1;  	}  } -static void router_id_set(struct prefix *p, struct zebra_vrf *zvrf) +static int router_id_set(afi_t afi, struct prefix *p, struct zebra_vrf *zvrf)  {  	struct prefix p2;  	struct listnode *node;  	struct zserv *client; -	zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; +	switch (afi) { +	case AFI_IP: +		zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; +		break; +	case AFI_IP6: +		zvrf->rid6_user_assigned.u.prefix6 = p->u.prefix6; +		break; +	default: +		return -1; +	} -	router_id_get(&p2, zvrf); +	router_id_get(afi, &p2, zvrf);  	for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) -		zsend_router_id_update(client, &p2, zvrf->vrf->vrf_id); +		zsend_router_id_update(client, afi, &p2, zvrf->vrf->vrf_id); + +	return 0;  }  void router_id_add_address(struct connected *ifc) @@ -113,27 +152,42 @@ void router_id_add_address(struct connected *ifc)  	struct prefix after;  	struct zserv *client;  	struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); +	afi_t afi; +	struct list *rid_lo; +	struct list *rid_all;  	if (router_id_bad_address(ifc))  		return; -	router_id_get(&before, zvrf); +	switch (ifc->address->family) { +	case AF_INET: +		afi = AFI_IP; +		rid_lo = zvrf->rid_lo_sorted_list; +		rid_all = zvrf->rid_all_sorted_list; +		break; +	case AF_INET6: +		afi = AFI_IP6; +		rid_lo = zvrf->rid6_lo_sorted_list; +		rid_all = zvrf->rid6_all_sorted_list; +		break; +	default: +		return; +	} -	if (if_is_loopback(ifc->ifp)) -		l = zvrf->rid_lo_sorted_list; -	else -		l = zvrf->rid_all_sorted_list; +	router_id_get(afi, &before, zvrf); + +	l = if_is_loopback(ifc->ifp) ? rid_lo : rid_all;  	if (!router_id_find_node(l, ifc))  		listnode_add_sort(l, ifc); -	router_id_get(&after, zvrf); +	router_id_get(afi, &after, zvrf);  	if (prefix_same(&before, &after))  		return;  	for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) -		zsend_router_id_update(client, &after, zvrf_id(zvrf)); +		zsend_router_id_update(client, afi, &after, zvrf_id(zvrf));  }  void router_id_del_address(struct connected *ifc) @@ -145,27 +199,45 @@ void router_id_del_address(struct connected *ifc)  	struct listnode *node;  	struct zserv *client;  	struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); +	afi_t afi; +	struct list *rid_lo; +	struct list *rid_all;  	if (router_id_bad_address(ifc))  		return; -	router_id_get(&before, zvrf); +	switch (ifc->address->family) { +	case AF_INET: +		afi = AFI_IP; +		rid_lo = zvrf->rid_lo_sorted_list; +		rid_all = zvrf->rid_all_sorted_list; +		break; +	case AF_INET6: +		afi = AFI_IP6; +		rid_lo = zvrf->rid6_lo_sorted_list; +		rid_all = zvrf->rid6_all_sorted_list; +		break; +	default: +		return; +	} + +	router_id_get(afi, &before, zvrf);  	if (if_is_loopback(ifc->ifp)) -		l = zvrf->rid_lo_sorted_list; +		l = rid_lo;  	else -		l = zvrf->rid_all_sorted_list; +		l = rid_all;  	if ((c = router_id_find_node(l, ifc)))  		listnode_delete(l, c); -	router_id_get(&after, zvrf); +	router_id_get(afi, &after, zvrf);  	if (prefix_same(&before, &after))  		return;  	for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) -		zsend_router_id_update(client, &after, zvrf_id(zvrf)); +		zsend_router_id_update(client, afi, &after, zvrf_id(zvrf));  }  void router_id_write(struct vty *vty, struct zebra_vrf *zvrf) @@ -178,70 +250,147 @@ void router_id_write(struct vty *vty, struct zebra_vrf *zvrf)  		snprintf(space, sizeof(space), "%s", " ");  	if (zvrf->rid_user_assigned.u.prefix4.s_addr != INADDR_ANY) { -		vty_out(vty, "%srouter-id %s\n", space, -			inet_ntoa(zvrf->rid_user_assigned.u.prefix4)); +		vty_out(vty, "%sip router-id %pI4\n", space, +			&zvrf->rid_user_assigned.u.prefix4); +	} +	if (!router_id_v6_is_any(&zvrf->rid6_user_assigned)) { +		vty_out(vty, "%sipv6 router-id %pI6\n", space, +			&zvrf->rid_user_assigned.u.prefix6);  	}  } -DEFUN (router_id, -       router_id_cmd, -       "router-id A.B.C.D vrf NAME", +DEFUN (ip_router_id, +       ip_router_id_cmd, +       "ip router-id A.B.C.D vrf NAME", +       IP_STR         "Manually set the router-id\n" -       "IP address to use for router-id\n" VRF_CMD_HELP_STR) +       "IP address to use for router-id\n" +       VRF_CMD_HELP_STR)  { -	int idx_ipv4 = 1; -	int idx_name = 3; +	int idx = 0; +	struct prefix rid; +	vrf_id_t vrf_id;  	struct zebra_vrf *zvrf; -	struct prefix rid; -	vrf_id_t vrf_id = VRF_DEFAULT; +	argv_find(argv, argc, "A.B.C.D", &idx); -	rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); -	if (!rid.u.prefix4.s_addr) +	if (!inet_pton(AF_INET, argv[idx]->arg, &rid.u.prefix4))  		return CMD_WARNING_CONFIG_FAILED;  	rid.prefixlen = 32;  	rid.family = AF_INET; -	if (argc > 2) -		VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); +	argv_find(argv, argc, "NAME", &idx); +	VRF_GET_ID(vrf_id, argv[idx]->arg, false);  	zvrf = vrf_info_lookup(vrf_id); -	router_id_set(&rid, zvrf); +	router_id_set(AFI_IP, &rid, zvrf);  	return CMD_SUCCESS;  } -DEFUN (router_id_in_vrf, -       router_id_in_vrf_cmd, -       "router-id A.B.C.D", +ALIAS (ip_router_id, +       router_id_cmd, +       "router-id A.B.C.D vrf NAME", +       "Manually set the router-id\n" +       "IP address to use for router-id\n" +       VRF_CMD_HELP_STR); + +DEFUN (ipv6_router_id, +       ipv6_router_id_cmd, +       "ipv6 router-id X:X::X:X vrf NAME", +       IPV6_STR +       "Manually set the router-id\n" +       "IPv6 address to use for router-id\n" +       VRF_CMD_HELP_STR) +{ +	int idx = 0; +	struct prefix rid; +	vrf_id_t vrf_id; +	struct zebra_vrf *zvrf; + +	argv_find(argv, argc, "X:X::X:X", &idx); + +	if (!inet_pton(AF_INET6, argv[idx]->arg, &rid.u.prefix6)) +		return CMD_WARNING_CONFIG_FAILED; + +	rid.prefixlen = 128; +	rid.family = AF_INET6; + +	argv_find(argv, argc, "NAME", &idx); +	VRF_GET_ID(vrf_id, argv[idx]->arg, false); + +	zvrf = vrf_info_lookup(vrf_id); +	router_id_set(AFI_IP6, &rid, zvrf); + +	return CMD_SUCCESS; +} + + +DEFUN (ip_router_id_in_vrf, +       ip_router_id_in_vrf_cmd, +       "ip router-id A.B.C.D", +       IP_STR         "Manuall set the router-id\n"         "IP address to use for router-id\n")  {  	ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); -	int idx_ipv4 = 1; +	int idx = 0;  	struct prefix rid; -	rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); -	if (!rid.u.prefix4.s_addr) +	argv_find(argv, argc, "A.B.C.D", &idx); + +	if (!inet_pton(AF_INET, argv[idx]->arg, &rid.u.prefix4))  		return CMD_WARNING_CONFIG_FAILED;  	rid.prefixlen = 32;  	rid.family = AF_INET; -	router_id_set(&rid, zvrf); +	router_id_set(AFI_IP, &rid, zvrf);  	return CMD_SUCCESS;  } -DEFUN (no_router_id, -       no_router_id_cmd, -       "no router-id [A.B.C.D vrf NAME]", +ALIAS (ip_router_id_in_vrf, +       router_id_in_vrf_cmd, +       "router-id A.B.C.D", +       "Manually set the router-id\n" +       "IP address to use for router-id\n"); + +DEFUN (ipv6_router_id_in_vrf, +       ipv6_router_id_in_vrf_cmd, +       "ipv6 router-id X:X::X:X", +       IP6_STR +       "Manuall set the IPv6 router-id\n" +       "IPV6 address to use for router-id\n") +{ +	ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); +	int idx = 0; +	struct prefix rid; + +	argv_find(argv, argc, "X:X::X:X", &idx); + +	if (!inet_pton(AF_INET6, argv[idx]->arg, &rid.u.prefix6)) +		return CMD_WARNING_CONFIG_FAILED; + +	rid.prefixlen = 128; +	rid.family = AF_INET6; + +	router_id_set(AFI_IP6, &rid, zvrf); + +	return CMD_SUCCESS; +} + +DEFUN (no_ip_router_id, +       no_ip_router_id_cmd, +       "no ip router-id [A.B.C.D vrf NAME]",         NO_STR +       IP_STR         "Remove the manually configured router-id\n" -       "IP address to use for router-id\n" VRF_CMD_HELP_STR) +       "IP address to use for router-id\n" +       VRF_CMD_HELP_STR)  { -	int idx_name = 4; +	int idx = 0;  	struct prefix rid;  	vrf_id_t vrf_id = VRF_DEFAULT;  	struct zebra_vrf *zvrf; @@ -250,19 +399,54 @@ DEFUN (no_router_id,  	rid.prefixlen = 0;  	rid.family = AF_INET; -	if (argc > 3) -		VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); +	if (argv_find(argv, argc, "NAME", &idx)) +		VRF_GET_ID(vrf_id, argv[idx]->arg, false); -	zvrf = vrf_info_get(vrf_id); -	router_id_set(&rid, zvrf); +	zvrf = vrf_info_lookup(vrf_id); +	router_id_set(AFI_IP, &rid, zvrf);  	return CMD_SUCCESS;  } -DEFUN (no_router_id_in_vrf, -       no_router_id_in_vrf_cmd, -       "no router-id [A.B.C.D]", +ALIAS (no_ip_router_id, +       no_router_id_cmd, +       "no router-id [A.B.C.D vrf NAME]", +       NO_STR +       "Remove the manually configured router-id\n" +       "IP address to use for router-id\n" +       VRF_CMD_HELP_STR); + +DEFUN (no_ipv6_router_id, +       no_ipv6_router_id_cmd, +       "no ipv6 router-id [X:X::X:X vrf NAME]", +       NO_STR +       IPV6_STR +       "Remove the manually configured IPv6 router-id\n" +       "IPv6 address to use for router-id\n" +       VRF_CMD_HELP_STR) +{ +	int idx = 0; +	struct prefix rid; +	vrf_id_t vrf_id = VRF_DEFAULT; +	struct zebra_vrf *zvrf; + +	memset(&rid, 0, sizeof(rid)); +	rid.family = AF_INET; + +	if (argv_find(argv, argc, "NAME", &idx)) +		VRF_GET_ID(vrf_id, argv[idx]->arg, false); + +	zvrf = vrf_info_lookup(vrf_id); +	router_id_set(AFI_IP6, &rid, zvrf); + +	return CMD_SUCCESS; +} + +DEFUN (no_ip_router_id_in_vrf, +       no_ip_router_id_in_vrf_cmd, +       "no ip router-id [A.B.C.D]",         NO_STR +       IP_STR         "Remove the manually configured router-id\n"         "IP address to use for router-id\n")  { @@ -274,40 +458,81 @@ DEFUN (no_router_id_in_vrf,  	rid.prefixlen = 0;  	rid.family = AF_INET; -	router_id_set(&rid, zvrf); +	router_id_set(AFI_IP, &rid, zvrf);  	return CMD_SUCCESS;  } -DEFUN (show_router_id, -       show_router_id_cmd, -       "show router-id [vrf NAME]", +ALIAS (no_ip_router_id_in_vrf, +       no_router_id_in_vrf_cmd, +       "no router-id [A.B.C.D]", +       NO_STR +       "Remove the manually configured router-id\n" +       "IP address to use for router-id\n"); + +DEFUN (no_ipv6_router_id_in_vrf, +       no_ipv6_router_id_in_vrf_cmd, +       "no ipv6 router-id [X:X::X:X]", +       NO_STR +       IP6_STR +       "Remove the manually configured IPv6 router-id\n" +       "IPv6 address to use for router-id\n") +{ +	ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + +	struct prefix rid; + +	memset(&rid, 0, sizeof(rid)); +	rid.family = AF_INET; + +	router_id_set(AFI_IP6, &rid, zvrf); + +	return CMD_SUCCESS; +} + +DEFUN (show_ip_router_id, +       show_ip_router_id_cmd, +       "show [ip|ipv6] router-id [vrf NAME]",         SHOW_STR +       IP_STR +       IPV6_STR         "Show the configured router-id\n"         VRF_CMD_HELP_STR)  { -        int idx_name = 3; +	int idx = 0; +	vrf_id_t vrf_id = VRF_DEFAULT; +	struct zebra_vrf *zvrf; +	const char *vrf_name = "default"; +	char addr_name[INET6_ADDRSTRLEN]; +	int is_ipv6 = 0; -        vrf_id_t vrf_id = VRF_DEFAULT; -        struct zebra_vrf *zvrf; +	is_ipv6 = argv_find(argv, argc, "ipv6", &idx); -        if (argc > 2) -                VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); +	if (argv_find(argv, argc, "NAME", &idx)) { +		VRF_GET_ID(vrf_id, argv[idx]->arg, false); +		vrf_name = argv[idx]->arg; +	} -        zvrf = vrf_info_get(vrf_id); +	zvrf = vrf_info_get(vrf_id); -        if ((zvrf != NULL) && (zvrf->rid_user_assigned.u.prefix4.s_addr)) { -                vty_out(vty, "zebra:\n"); -                if (vrf_id == VRF_DEFAULT) -                        vty_out(vty, "     router-id %s vrf default\n", -                                inet_ntoa(zvrf->rid_user_assigned.u.prefix4)); -                else -                        vty_out(vty, "     router-id %s vrf %s\n", -                                inet_ntoa(zvrf->rid_user_assigned.u.prefix4), -                                argv[idx_name]->arg); -        } +	if (zvrf != NULL) { +		if (is_ipv6) { +			if (router_id_v6_is_any(&zvrf->rid6_user_assigned)) +				return CMD_SUCCESS; +			inet_ntop(AF_INET6, &zvrf->rid6_user_assigned.u.prefix6, +				  addr_name, sizeof(addr_name)); +		} else { +			if (zvrf->rid_user_assigned.u.prefix4.s_addr == 0) +				return CMD_SUCCESS; +			inet_ntop(AF_INET, &zvrf->rid_user_assigned.u.prefix4, +				  addr_name, sizeof(addr_name)); +		} + +		vty_out(vty, "zebra:\n"); +		vty_out(vty, "     router-id %s vrf %s\n", addr_name, vrf_name); +	} -        return CMD_SUCCESS; +	return CMD_SUCCESS;  }  static int router_id_cmp(void *a, void *b) @@ -319,30 +544,62 @@ static int router_id_cmp(void *a, void *b)  			     &ifb->address->u.prefix4.s_addr);  } +static int router_id_v6_cmp(void *a, void *b) +{ +	const struct connected *ifa = (const struct connected *)a; +	const struct connected *ifb = (const struct connected *)b; + +	return IPV6_ADDR_CMP(&ifa->address->u.prefix6, +			     &ifb->address->u.prefix6); +} +  void router_id_cmd_init(void)  { +	install_element(CONFIG_NODE, &ip_router_id_cmd);  	install_element(CONFIG_NODE, &router_id_cmd); +	install_element(CONFIG_NODE, &ipv6_router_id_cmd); +	install_element(CONFIG_NODE, &no_ip_router_id_cmd);  	install_element(CONFIG_NODE, &no_router_id_cmd); +	install_element(CONFIG_NODE, &ip_router_id_in_vrf_cmd); +	install_element(VRF_NODE, &ip_router_id_in_vrf_cmd);  	install_element(CONFIG_NODE, &router_id_in_vrf_cmd);  	install_element(VRF_NODE, &router_id_in_vrf_cmd); +	install_element(CONFIG_NODE, &ipv6_router_id_in_vrf_cmd); +	install_element(VRF_NODE, &ipv6_router_id_in_vrf_cmd); +	install_element(CONFIG_NODE, &no_ipv6_router_id_cmd); +	install_element(CONFIG_NODE, &no_ip_router_id_in_vrf_cmd); +	install_element(VRF_NODE, &no_ip_router_id_in_vrf_cmd);  	install_element(CONFIG_NODE, &no_router_id_in_vrf_cmd);  	install_element(VRF_NODE, &no_router_id_in_vrf_cmd); -	install_element(VIEW_NODE, &show_router_id_cmd); +	install_element(CONFIG_NODE, &no_ipv6_router_id_in_vrf_cmd); +	install_element(VRF_NODE, &no_ipv6_router_id_in_vrf_cmd); +	install_element(VIEW_NODE, &show_ip_router_id_cmd);  }  void router_id_init(struct zebra_vrf *zvrf)  {  	zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list;  	zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; +	zvrf->rid6_all_sorted_list = &zvrf->_rid6_all_sorted_list; +	zvrf->rid6_lo_sorted_list = &zvrf->_rid6_lo_sorted_list;  	memset(zvrf->rid_all_sorted_list, 0,  	       sizeof(zvrf->_rid_all_sorted_list));  	memset(zvrf->rid_lo_sorted_list, 0, sizeof(zvrf->_rid_lo_sorted_list));  	memset(&zvrf->rid_user_assigned, 0, sizeof(zvrf->rid_user_assigned)); +	memset(zvrf->rid6_all_sorted_list, 0, +	       sizeof(zvrf->_rid6_all_sorted_list)); +	memset(zvrf->rid6_lo_sorted_list, 0, +	       sizeof(zvrf->_rid6_lo_sorted_list)); +	memset(&zvrf->rid6_user_assigned, 0, sizeof(zvrf->rid6_user_assigned));  	zvrf->rid_all_sorted_list->cmp = router_id_cmp;  	zvrf->rid_lo_sorted_list->cmp = router_id_cmp; +	zvrf->rid6_all_sorted_list->cmp = router_id_v6_cmp; +	zvrf->rid6_lo_sorted_list->cmp = router_id_v6_cmp;  	zvrf->rid_user_assigned.family = AF_INET;  	zvrf->rid_user_assigned.prefixlen = 32; +	zvrf->rid6_user_assigned.family = AF_INET6; +	zvrf->rid6_user_assigned.prefixlen = 128;  } diff --git a/zebra/router-id.h b/zebra/router-id.h index c69c321fda..4a35f6605b 100644 --- a/zebra/router-id.h +++ b/zebra/router-id.h @@ -39,7 +39,7 @@ extern void router_id_del_address(struct connected *c);  extern void router_id_init(struct zebra_vrf *zvrf);  extern void router_id_cmd_init(void);  extern void router_id_write(struct vty *vty, struct zebra_vrf *zvrf); -extern void router_id_get(struct prefix *p, struct zebra_vrf *zvrf); +extern int router_id_get(afi_t afi, struct prefix *p, struct zebra_vrf *zvrf);  #ifdef __cplusplus  } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 0a459b4d0a..48aa566136 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -907,17 +907,18 @@ void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable,  	zserv_send_message(client, s);  } -/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ -int zsend_router_id_update(struct zserv *client, struct prefix *p, +/* Router-id is updated. Send ZEBRA_ROUTER_ID_UPDATE to client. */ +int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p,  			   vrf_id_t vrf_id)  {  	int blen; +	struct stream *s;  	/* Check this client need interface information. */ -	if (!vrf_bitmap_check(client->ridinfo, vrf_id)) +	if (!vrf_bitmap_check(client->ridinfo[afi], vrf_id))  		return 0; -	struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); +	s = stream_new(ZEBRA_MAX_PACKET_SIZ);  	/* Message type. */  	zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); @@ -1897,20 +1898,48 @@ stream_failure:  /* Register zebra server router-id information.  Send current router-id */  static void zread_router_id_add(ZAPI_HANDLER_ARGS)  { +	afi_t afi; +  	struct prefix p; +	STREAM_GETW(msg, afi); + +	if (afi <= AFI_UNSPEC || afi >= AFI_MAX) { +		zlog_warn( +			"Invalid AFI %u while registering for router ID notifications", +			afi); +		goto stream_failure; +	} +  	/* Router-id information is needed. */ -	vrf_bitmap_set(client->ridinfo, zvrf_id(zvrf)); +	vrf_bitmap_set(client->ridinfo[afi], zvrf_id(zvrf)); -	router_id_get(&p, zvrf); +	router_id_get(afi, &p, zvrf); -	zsend_router_id_update(client, &p, zvrf_id(zvrf)); +	zsend_router_id_update(client, afi, &p, zvrf_id(zvrf)); + +stream_failure: +	return;  }  /* Unregister zebra server router-id information. */  static void zread_router_id_delete(ZAPI_HANDLER_ARGS)  { -	vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); +	afi_t afi; + +	STREAM_GETW(msg, afi); + +	if (afi <= AFI_UNSPEC || afi >= AFI_MAX) { +		zlog_warn( +			"Invalid AFI %u while unregistering from router ID notifications", +			afi); +		goto stream_failure; +	} + +	vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf)); + +stream_failure: +	return;  }  static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf) @@ -1999,8 +2028,8 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)  		for (i = 0; i < ZEBRA_ROUTE_MAX; i++)  			vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));  		vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf)); +		vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));  	} -	vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));  }  /* diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index eb50e3c410..13beb6a273 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -68,8 +68,8 @@ extern int zsend_redistribute_route(int cmd, struct zserv *zclient,  				    const struct prefix *src_p,  				    const struct route_entry *re); -extern int zsend_router_id_update(struct zserv *zclient, struct prefix *p, -				  vrf_id_t vrf_id); +extern int zsend_router_id_update(struct zserv *zclient, afi_t afi, +				  struct prefix *p, vrf_id_t vrf_id);  extern int zsend_interface_vrf_update(struct zserv *zclient,  				      struct interface *ifp, vrf_id_t vrf_id);  extern int zsend_interface_link_params(struct zserv *zclient, diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index d262faa070..d200f5a4c8 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -92,6 +92,11 @@ struct zebra_vrf {  	struct list *rid_all_sorted_list;  	struct list *rid_lo_sorted_list;  	struct prefix rid_user_assigned; +	struct list _rid6_all_sorted_list; +	struct list _rid6_lo_sorted_list; +	struct list *rid6_all_sorted_list; +	struct list *rid6_lo_sorted_list; +	struct prefix rid6_user_assigned;  	/*  	 * Back pointer to the owning namespace. diff --git a/zebra/zserv.c b/zebra/zserv.c index f1b7dcc848..cded6ea12b 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -628,8 +628,8 @@ static void zserv_client_free(struct zserv *client)  		}  		vrf_bitmap_free(client->redist_default[afi]); +		vrf_bitmap_free(client->ridinfo[afi]);  	} -	vrf_bitmap_free(client->ridinfo);  	/*  	 * If any instance are graceful restart enabled, @@ -750,8 +750,8 @@ static struct zserv *zserv_client_create(int sock)  		for (i = 0; i < ZEBRA_ROUTE_MAX; i++)  			client->redist[afi][i] = vrf_bitmap_init();  		client->redist_default[afi] = vrf_bitmap_init(); +		client->ridinfo[afi] = vrf_bitmap_init();  	} -	client->ridinfo = vrf_bitmap_init();  	/* Add this client to linked list. */  	frr_with_mutex(&client_mutex) { diff --git a/zebra/zserv.h b/zebra/zserv.h index e904460782..54e840cd56 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -135,7 +135,7 @@ struct zserv {  	vrf_bitmap_t redist_default[AFI_MAX];  	/* Router-id information. */ -	vrf_bitmap_t ridinfo; +	vrf_bitmap_t ridinfo[AFI_MAX];  	bool notify_owner;  | 
