mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 18:20:15 +00:00
Merge pull request #3548 from opensourcerouting/rip-vrf
rip(ng)d: add VRF support
This commit is contained in:
commit
f61f266a0e
8
lib/if.c
8
lib/if.c
@ -1310,7 +1310,7 @@ static int lib_interface_create(enum nb_event event,
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int lib_interface_delete(enum nb_event event,
|
||||
static int lib_interface_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct interface *ifp;
|
||||
@ -1357,7 +1357,7 @@ static int lib_interface_description_modify(enum nb_event event,
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int lib_interface_description_delete(enum nb_event event,
|
||||
static int lib_interface_description_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct interface *ifp;
|
||||
@ -1378,13 +1378,13 @@ const struct frr_yang_module_info frr_interface_info = {
|
||||
{
|
||||
.xpath = "/frr-interface:lib/interface",
|
||||
.cbs.create = lib_interface_create,
|
||||
.cbs.destroy = lib_interface_delete,
|
||||
.cbs.destroy = lib_interface_destroy,
|
||||
.cbs.cli_show = cli_show_interface,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-interface:lib/interface/description",
|
||||
.cbs.modify = lib_interface_description_modify,
|
||||
.cbs.destroy = lib_interface_description_delete,
|
||||
.cbs.destroy = lib_interface_description_destroy,
|
||||
.cbs.cli_show = cli_show_interface_desc,
|
||||
},
|
||||
{
|
||||
|
@ -1297,7 +1297,7 @@ DEFPY (show_yang_operational_data,
|
||||
yang_dnode_free(dnode);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
lyd_validate(&dnode, LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB, ly_ctx);
|
||||
lyd_validate(&dnode, LYD_OPT_GET, ly_ctx);
|
||||
|
||||
/* Display the data. */
|
||||
if (lyd_print_mem(&strp, dnode, format,
|
||||
|
@ -573,7 +573,7 @@ static int vrf_default_accepts_vrf(int type)
|
||||
|
||||
/* Create a socket for the VRF. */
|
||||
int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
|
||||
char *interfacename)
|
||||
const char *interfacename)
|
||||
{
|
||||
int ret, save_errno, ret2;
|
||||
|
||||
@ -944,7 +944,7 @@ vrf_id_t vrf_get_default_id(void)
|
||||
return VRF_DEFAULT_INTERNAL;
|
||||
}
|
||||
|
||||
int vrf_bind(vrf_id_t vrf_id, int fd, char *name)
|
||||
int vrf_bind(vrf_id_t vrf_id, int fd, const char *name)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@ -1003,7 +1003,7 @@ int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params)
|
||||
}
|
||||
|
||||
int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
|
||||
char *interfacename)
|
||||
const char *interfacename)
|
||||
{
|
||||
int ret, save_errno, ret2;
|
||||
|
||||
|
@ -220,12 +220,12 @@ extern void vrf_terminate(void);
|
||||
|
||||
/* Create a socket serving for the given VRF */
|
||||
extern int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
|
||||
char *name);
|
||||
const char *name);
|
||||
|
||||
extern int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
|
||||
char *name);
|
||||
const char *name);
|
||||
|
||||
extern int vrf_bind(vrf_id_t vrf_id, int fd, char *name);
|
||||
extern int vrf_bind(vrf_id_t vrf_id, int fd, const char *name);
|
||||
|
||||
/* VRF ioctl operations */
|
||||
extern int vrf_getaddrinfo(const char *node, const char *service,
|
||||
|
19
lib/yang.c
19
lib/yang.c
@ -610,6 +610,25 @@ struct list *yang_data_list_new(void)
|
||||
return list;
|
||||
}
|
||||
|
||||
struct yang_data *yang_data_list_find(const struct list *list,
|
||||
const char *xpath_fmt, ...)
|
||||
{
|
||||
char xpath[XPATH_MAXLEN];
|
||||
struct yang_data *data;
|
||||
struct listnode *node;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, xpath_fmt);
|
||||
vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(list, node, data))
|
||||
if (strmatch(data->xpath, xpath))
|
||||
return data;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *ly_dup_cb(const void *priv)
|
||||
{
|
||||
/* Make a shallow copy of the priv pointer. */
|
||||
|
15
lib/yang.h
15
lib/yang.h
@ -513,6 +513,21 @@ extern void yang_data_free(struct yang_data *data);
|
||||
*/
|
||||
extern struct list *yang_data_list_new(void);
|
||||
|
||||
/*
|
||||
* Find the yang_data structure corresponding to an XPath in a list.
|
||||
*
|
||||
* list
|
||||
* list of yang_data structures to operate on.
|
||||
*
|
||||
* xpath_fmt
|
||||
* XPath to search for (format string).
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to yang_data if found, NULL otherwise.
|
||||
*/
|
||||
extern struct yang_data *yang_data_list_find(const struct list *list,
|
||||
const char *xpath_fmt, ...);
|
||||
|
||||
/*
|
||||
* Create and set up a libyang context (for use by the translator)
|
||||
*/
|
||||
|
@ -39,31 +39,46 @@
|
||||
*/
|
||||
DEFPY_NOSH (router_rip,
|
||||
router_rip_cmd,
|
||||
"router rip",
|
||||
"router rip [vrf NAME]",
|
||||
"Enable a routing process\n"
|
||||
"Routing Information Protocol (RIP)\n")
|
||||
"Routing Information Protocol (RIP)\n"
|
||||
VRF_CMD_HELP_STR)
|
||||
{
|
||||
char xpath[XPATH_MAXLEN];
|
||||
int ret;
|
||||
|
||||
nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_CREATE,
|
||||
NULL);
|
||||
/* Build RIP instance XPath. */
|
||||
if (!vrf)
|
||||
vrf = VRF_DEFAULT_NAME;
|
||||
snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']",
|
||||
vrf);
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
|
||||
ret = nb_cli_apply_changes(vty, NULL);
|
||||
if (ret == CMD_SUCCESS)
|
||||
VTY_PUSH_XPATH(RIP_NODE, "/frr-ripd:ripd/instance");
|
||||
VTY_PUSH_XPATH(RIP_NODE, xpath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFPY (no_router_rip,
|
||||
no_router_rip_cmd,
|
||||
"no router rip",
|
||||
"no router rip [vrf NAME]",
|
||||
NO_STR
|
||||
"Enable a routing process\n"
|
||||
"Routing Information Protocol (RIP)\n")
|
||||
"Routing Information Protocol (RIP)\n"
|
||||
VRF_CMD_HELP_STR)
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_DESTROY,
|
||||
NULL);
|
||||
char xpath[XPATH_MAXLEN];
|
||||
|
||||
/* Build RIP instance XPath. */
|
||||
if (!vrf)
|
||||
vrf = VRF_DEFAULT_NAME;
|
||||
snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']",
|
||||
vrf);
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
@ -71,8 +86,15 @@ DEFPY (no_router_rip,
|
||||
void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults)
|
||||
{
|
||||
const char *vrf_name;
|
||||
|
||||
vrf_name = yang_dnode_get_string(dnode, "./vrf");
|
||||
|
||||
vty_out(vty, "!\n");
|
||||
vty_out(vty, "router rip\n");
|
||||
vty_out(vty, "router rip");
|
||||
if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
|
||||
vty_out(vty, " vrf %s", vrf_name);
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -902,7 +924,7 @@ DEFPY (no_ip_rip_authentication_string,
|
||||
"Authentication string\n"
|
||||
"Authentication string\n")
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_MODIFY,
|
||||
nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_DESTROY,
|
||||
NULL);
|
||||
|
||||
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
|
||||
@ -970,12 +992,24 @@ void cli_show_ip_rip_authentication_key_chain(struct vty *vty,
|
||||
*/
|
||||
DEFPY (clear_ip_rip,
|
||||
clear_ip_rip_cmd,
|
||||
"clear ip rip",
|
||||
"clear ip rip [vrf WORD]",
|
||||
CLEAR_STR
|
||||
IP_STR
|
||||
"Clear IP RIP database\n")
|
||||
"Clear IP RIP database\n"
|
||||
VRF_CMD_HELP_STR)
|
||||
{
|
||||
return nb_cli_rpc("/frr-ripd:clear-rip-route", NULL, NULL);
|
||||
struct list *input;
|
||||
|
||||
input = list_new();
|
||||
if (vrf) {
|
||||
struct yang_data *yang_vrf;
|
||||
|
||||
yang_vrf = yang_data_new("/frr-ripd:clear-rip-route/input/vrf",
|
||||
vrf);
|
||||
listnode_add(input, yang_vrf);
|
||||
}
|
||||
|
||||
return nb_cli_rpc("/frr-ripd:clear-rip-route", input, NULL);
|
||||
}
|
||||
|
||||
void rip_cli_init(void)
|
||||
|
@ -50,9 +50,9 @@ DEFINE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc))
|
||||
static void rip_enable_apply(struct interface *);
|
||||
static void rip_passive_interface_apply(struct interface *);
|
||||
static int rip_if_down(struct interface *ifp);
|
||||
static int rip_enable_if_lookup(const char *ifname);
|
||||
static int rip_enable_if_lookup(struct rip *rip, const char *ifname);
|
||||
static int rip_enable_network_lookup2(struct connected *connected);
|
||||
static void rip_enable_apply_all(void);
|
||||
static void rip_enable_apply_all(struct rip *rip);
|
||||
|
||||
const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"},
|
||||
{RI_RIP_VERSION_2, "2"},
|
||||
@ -60,15 +60,6 @@ const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"},
|
||||
{RI_RIP_VERSION_NONE, "none"},
|
||||
{0}};
|
||||
|
||||
/* RIP enabled network vector. */
|
||||
vector rip_enable_interface;
|
||||
|
||||
/* RIP enabled interface table. */
|
||||
struct route_table *rip_enable_network;
|
||||
|
||||
/* Vector to store passive-interface name. */
|
||||
vector Vrip_passive_nondefault;
|
||||
|
||||
/* Join to the RIP version 2 multicast group. */
|
||||
static int ipv4_multicast_join(int sock, struct in_addr group,
|
||||
struct in_addr ifa, ifindex_t ifindex)
|
||||
@ -208,7 +199,7 @@ static void rip_request_interface(struct interface *ifp)
|
||||
|
||||
/* If there is no version configuration in the interface,
|
||||
use rip's version setting. */
|
||||
vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? rip->version_send
|
||||
vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? ri->rip->version_send
|
||||
: ri->ri_send);
|
||||
if (vsend & RIPv1)
|
||||
rip_request_interface_send(ifp, RIPv1);
|
||||
@ -329,12 +320,11 @@ static int rip_if_ipv4_address_check(struct interface *ifp)
|
||||
|
||||
|
||||
/* Does this address belongs to me ? */
|
||||
int if_check_address(struct in_addr addr)
|
||||
int if_check_address(struct rip *rip, struct in_addr addr)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
FOR_ALL_INTERFACES (rip->vrf, ifp) {
|
||||
struct listnode *cnode;
|
||||
struct connected *connected;
|
||||
|
||||
@ -369,13 +359,14 @@ int rip_interface_down(int command, struct zclient *zclient,
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
rip_interface_sync(ifp);
|
||||
rip_if_down(ifp);
|
||||
|
||||
if (IS_RIP_DEBUG_ZEBRA)
|
||||
zlog_debug(
|
||||
"interface %s index %d flags %llx metric %d mtu %d is down",
|
||||
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
|
||||
ifp->metric, ifp->mtu);
|
||||
"interface %s vrf %u index %d flags %llx metric %d mtu %d is down",
|
||||
ifp->name, ifp->vrf_id, ifp->ifindex,
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -395,9 +386,11 @@ int rip_interface_up(int command, struct zclient *zclient, zebra_size_t length,
|
||||
|
||||
if (IS_RIP_DEBUG_ZEBRA)
|
||||
zlog_debug(
|
||||
"interface %s index %d flags %#llx metric %d mtu %d is up",
|
||||
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
|
||||
ifp->metric, ifp->mtu);
|
||||
"interface %s vrf %u index %d flags %#llx metric %d mtu %d is up",
|
||||
ifp->name, ifp->vrf_id, ifp->ifindex,
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
|
||||
|
||||
rip_interface_sync(ifp);
|
||||
|
||||
/* Check if this interface is RIP enabled or not.*/
|
||||
rip_enable_apply(ifp);
|
||||
@ -418,12 +411,13 @@ int rip_interface_add(int command, struct zclient *zclient, zebra_size_t length,
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
|
||||
rip_interface_sync(ifp);
|
||||
|
||||
if (IS_RIP_DEBUG_ZEBRA)
|
||||
zlog_debug(
|
||||
"interface add %s index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
|
||||
ifp->metric, ifp->mtu);
|
||||
"interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->vrf_id, ifp->ifindex,
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
|
||||
|
||||
/* Check if this interface is RIP enabled or not.*/
|
||||
rip_enable_apply(ifp);
|
||||
@ -456,13 +450,15 @@ int rip_interface_delete(int command, struct zclient *zclient,
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
rip_interface_sync(ifp);
|
||||
if (if_is_up(ifp)) {
|
||||
rip_if_down(ifp);
|
||||
}
|
||||
|
||||
zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
|
||||
ifp->metric, ifp->mtu);
|
||||
zlog_info(
|
||||
"interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->vrf_id, ifp->ifindex,
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
|
||||
|
||||
/* To support pseudo interface do not free interface structure. */
|
||||
/* if_delete(ifp); */
|
||||
@ -471,6 +467,28 @@ int rip_interface_delete(int command, struct zclient *zclient,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* VRF update for an interface. */
|
||||
int rip_interface_vrf_update(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct interface *ifp;
|
||||
vrf_id_t new_vrf_id;
|
||||
|
||||
ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
|
||||
&new_vrf_id);
|
||||
if (!ifp)
|
||||
return 0;
|
||||
|
||||
if (IS_RIP_DEBUG_ZEBRA)
|
||||
zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
|
||||
ifp->name, vrf_id, new_vrf_id);
|
||||
|
||||
if_update_to_new_vrf(ifp, new_vrf_id);
|
||||
rip_interface_sync(ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rip_interface_clean(struct rip_interface *ri)
|
||||
{
|
||||
ri->enable_network = 0;
|
||||
@ -483,12 +501,11 @@ static void rip_interface_clean(struct rip_interface *ri)
|
||||
}
|
||||
}
|
||||
|
||||
void rip_interfaces_clean(void)
|
||||
void rip_interfaces_clean(struct rip *rip)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp)
|
||||
FOR_ALL_INTERFACES (rip->vrf, ifp)
|
||||
rip_interface_clean(ifp->info);
|
||||
}
|
||||
|
||||
@ -531,20 +548,22 @@ static void rip_interface_reset(struct rip_interface *ri)
|
||||
|
||||
int rip_if_down(struct interface *ifp)
|
||||
{
|
||||
struct rip *rip;
|
||||
struct route_node *rp;
|
||||
struct rip_info *rinfo;
|
||||
struct rip_interface *ri = NULL;
|
||||
struct list *list = NULL;
|
||||
struct listnode *listnode = NULL, *nextnode = NULL;
|
||||
|
||||
ri = ifp->info;
|
||||
rip = ri->rip;
|
||||
if (rip) {
|
||||
for (rp = route_top(rip->table); rp; rp = route_next(rp))
|
||||
if ((list = rp->info) != NULL)
|
||||
for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
|
||||
rinfo))
|
||||
if (rinfo->nh.ifindex == ifp->ifindex)
|
||||
rip_ecmp_delete(rinfo);
|
||||
|
||||
ri = ifp->info;
|
||||
rip_ecmp_delete(rip, rinfo);
|
||||
|
||||
if (ri->running) {
|
||||
if (IS_RIP_DEBUG_EVENT)
|
||||
@ -560,18 +579,10 @@ int rip_if_down(struct interface *ifp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Needed for stop RIP process. */
|
||||
void rip_if_down_all(void)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp)
|
||||
rip_if_down(ifp);
|
||||
}
|
||||
|
||||
static void rip_apply_address_add(struct connected *ifc)
|
||||
{
|
||||
struct rip_interface *ri = ifc->ifp->info;
|
||||
struct rip *rip = ri->rip;
|
||||
struct prefix_ipv4 address;
|
||||
struct nexthop nh;
|
||||
struct prefix *p;
|
||||
@ -597,10 +608,11 @@ static void rip_apply_address_add(struct connected *ifc)
|
||||
|
||||
/* Check if this interface is RIP enabled or not
|
||||
or Check if this address's prefix is RIP enabled */
|
||||
if ((rip_enable_if_lookup(ifc->ifp->name) >= 0)
|
||||
if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
|
||||
|| (rip_enable_network_lookup2(ifc) >= 0))
|
||||
rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
|
||||
&address, &nh, 0, 0, 0);
|
||||
rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
|
||||
RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
|
||||
0);
|
||||
}
|
||||
|
||||
int rip_interface_address_add(int command, struct zclient *zclient,
|
||||
@ -634,6 +646,8 @@ int rip_interface_address_add(int command, struct zclient *zclient,
|
||||
|
||||
static void rip_apply_address_del(struct connected *ifc)
|
||||
{
|
||||
struct rip_interface *ri = ifc->ifp->info;
|
||||
struct rip *rip = ri->rip;
|
||||
struct prefix_ipv4 address;
|
||||
struct prefix *p;
|
||||
|
||||
@ -651,7 +665,7 @@ static void rip_apply_address_del(struct connected *ifc)
|
||||
address.prefixlen = p->prefixlen;
|
||||
apply_mask_ipv4(&address);
|
||||
|
||||
rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
|
||||
rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
|
||||
&address, ifc->ifp->ifindex);
|
||||
}
|
||||
|
||||
@ -689,10 +703,15 @@ int rip_interface_address_delete(int command, struct zclient *zclient,
|
||||
* is within the ripng_enable_network table. */
|
||||
static int rip_enable_network_lookup_if(struct interface *ifp)
|
||||
{
|
||||
struct rip_interface *ri = ifp->info;
|
||||
struct rip *rip = ri->rip;
|
||||
struct listnode *node, *nnode;
|
||||
struct connected *connected;
|
||||
struct prefix_ipv4 address;
|
||||
|
||||
if (!rip)
|
||||
return -1;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
|
||||
struct prefix *p;
|
||||
struct route_node *n;
|
||||
@ -704,7 +723,7 @@ static int rip_enable_network_lookup_if(struct interface *ifp)
|
||||
address.prefix = p->u.prefix4;
|
||||
address.prefixlen = IPV4_MAX_BITLEN;
|
||||
|
||||
n = route_node_match(rip_enable_network,
|
||||
n = route_node_match(rip->enable_network,
|
||||
(struct prefix *)&address);
|
||||
if (n) {
|
||||
route_unlock_node(n);
|
||||
@ -716,8 +735,10 @@ static int rip_enable_network_lookup_if(struct interface *ifp)
|
||||
}
|
||||
|
||||
/* Check wether connected is within the ripng_enable_network table. */
|
||||
int rip_enable_network_lookup2(struct connected *connected)
|
||||
static int rip_enable_network_lookup2(struct connected *connected)
|
||||
{
|
||||
struct rip_interface *ri = connected->ifp->info;
|
||||
struct rip *rip = ri->rip;
|
||||
struct prefix_ipv4 address;
|
||||
struct prefix *p;
|
||||
|
||||
@ -731,8 +752,8 @@ int rip_enable_network_lookup2(struct connected *connected)
|
||||
address.prefixlen = IPV4_MAX_BITLEN;
|
||||
|
||||
/* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
|
||||
* rip_enable_network */
|
||||
node = route_node_match(rip_enable_network,
|
||||
* rip->enable_network */
|
||||
node = route_node_match(rip->enable_network,
|
||||
(struct prefix *)&address);
|
||||
|
||||
if (node) {
|
||||
@ -744,11 +765,11 @@ int rip_enable_network_lookup2(struct connected *connected)
|
||||
return -1;
|
||||
}
|
||||
/* Add RIP enable network. */
|
||||
int rip_enable_network_add(struct prefix *p)
|
||||
int rip_enable_network_add(struct rip *rip, struct prefix *p)
|
||||
{
|
||||
struct route_node *node;
|
||||
|
||||
node = route_node_get(rip_enable_network, p);
|
||||
node = route_node_get(rip->enable_network, p);
|
||||
|
||||
if (node->info) {
|
||||
route_unlock_node(node);
|
||||
@ -757,17 +778,17 @@ int rip_enable_network_add(struct prefix *p)
|
||||
node->info = (void *)1;
|
||||
|
||||
/* XXX: One should find a better solution than a generic one */
|
||||
rip_enable_apply_all();
|
||||
rip_enable_apply_all(rip);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/* Delete RIP enable network. */
|
||||
int rip_enable_network_delete(struct prefix *p)
|
||||
int rip_enable_network_delete(struct rip *rip, struct prefix *p)
|
||||
{
|
||||
struct route_node *node;
|
||||
|
||||
node = route_node_lookup(rip_enable_network, p);
|
||||
node = route_node_lookup(rip->enable_network, p);
|
||||
if (node) {
|
||||
node->info = NULL;
|
||||
|
||||
@ -778,7 +799,7 @@ int rip_enable_network_delete(struct prefix *p)
|
||||
route_unlock_node(node);
|
||||
|
||||
/* XXX: One should find a better solution than a generic one */
|
||||
rip_enable_apply_all();
|
||||
rip_enable_apply_all(rip);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -787,50 +808,53 @@ int rip_enable_network_delete(struct prefix *p)
|
||||
}
|
||||
|
||||
/* Check interface is enabled by ifname statement. */
|
||||
static int rip_enable_if_lookup(const char *ifname)
|
||||
static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
|
||||
{
|
||||
unsigned int i;
|
||||
char *str;
|
||||
|
||||
for (i = 0; i < vector_active(rip_enable_interface); i++)
|
||||
if ((str = vector_slot(rip_enable_interface, i)) != NULL)
|
||||
if (!rip)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < vector_active(rip->enable_interface); i++)
|
||||
if ((str = vector_slot(rip->enable_interface, i)) != NULL)
|
||||
if (strcmp(str, ifname) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add interface to rip_enable_if. */
|
||||
int rip_enable_if_add(const char *ifname)
|
||||
int rip_enable_if_add(struct rip *rip, const char *ifname)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rip_enable_if_lookup(ifname);
|
||||
ret = rip_enable_if_lookup(rip, ifname);
|
||||
if (ret >= 0)
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
|
||||
vector_set(rip_enable_interface,
|
||||
vector_set(rip->enable_interface,
|
||||
XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
|
||||
|
||||
rip_enable_apply_all(); /* TODOVJ */
|
||||
rip_enable_apply_all(rip); /* TODOVJ */
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/* Delete interface from rip_enable_if. */
|
||||
int rip_enable_if_delete(const char *ifname)
|
||||
int rip_enable_if_delete(struct rip *rip, const char *ifname)
|
||||
{
|
||||
int index;
|
||||
char *str;
|
||||
|
||||
index = rip_enable_if_lookup(ifname);
|
||||
index = rip_enable_if_lookup(rip, ifname);
|
||||
if (index < 0)
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
|
||||
str = vector_slot(rip_enable_interface, index);
|
||||
str = vector_slot(rip->enable_interface, index);
|
||||
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
|
||||
vector_unset(rip_enable_interface, index);
|
||||
vector_unset(rip->enable_interface, index);
|
||||
|
||||
rip_enable_apply_all(); /* TODOVJ */
|
||||
rip_enable_apply_all(rip); /* TODOVJ */
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -848,7 +872,7 @@ static int rip_interface_wakeup(struct thread *t)
|
||||
ri->t_wakeup = NULL;
|
||||
|
||||
/* Join to multicast group. */
|
||||
if (rip_multicast_join(ifp, rip->sock) < 0) {
|
||||
if (rip_multicast_join(ifp, ri->rip->sock) < 0) {
|
||||
flog_err_sys(EC_LIB_SOCKET,
|
||||
"multicast join failed, interface %s not running",
|
||||
ifp->name);
|
||||
@ -866,6 +890,8 @@ static int rip_interface_wakeup(struct thread *t)
|
||||
|
||||
static void rip_connect_set(struct interface *ifp, int set)
|
||||
{
|
||||
struct rip_interface *ri = ifp->info;
|
||||
struct rip *rip = ri->rip;
|
||||
struct listnode *node, *nnode;
|
||||
struct connected *connected;
|
||||
struct prefix_ipv4 address;
|
||||
@ -890,17 +916,18 @@ static void rip_connect_set(struct interface *ifp, int set)
|
||||
if (set) {
|
||||
/* Check once more wether this prefix is within a
|
||||
* "network IF_OR_PREF" one */
|
||||
if ((rip_enable_if_lookup(connected->ifp->name) >= 0)
|
||||
if ((rip_enable_if_lookup(rip, connected->ifp->name)
|
||||
>= 0)
|
||||
|| (rip_enable_network_lookup2(connected) >= 0))
|
||||
rip_redistribute_add(ZEBRA_ROUTE_CONNECT,
|
||||
rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
|
||||
RIP_ROUTE_INTERFACE,
|
||||
&address, &nh, 0, 0, 0);
|
||||
} else {
|
||||
rip_redistribute_delete(ZEBRA_ROUTE_CONNECT,
|
||||
rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
|
||||
RIP_ROUTE_INTERFACE, &address,
|
||||
connected->ifp->ifindex);
|
||||
if (rip_redistribute_check(ZEBRA_ROUTE_CONNECT))
|
||||
rip_redistribute_add(ZEBRA_ROUTE_CONNECT,
|
||||
if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
|
||||
rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
|
||||
RIP_ROUTE_REDISTRIBUTE,
|
||||
&address, &nh, 0, 0, 0);
|
||||
}
|
||||
@ -929,7 +956,7 @@ void rip_enable_apply(struct interface *ifp)
|
||||
ri->enable_network = 0;
|
||||
|
||||
/* Check interface name configuration. */
|
||||
ret = rip_enable_if_lookup(ifp->name);
|
||||
ret = rip_enable_if_lookup(ri->rip, ifp->name);
|
||||
if (ret >= 0)
|
||||
ri->enable_interface = 1;
|
||||
else
|
||||
@ -962,17 +989,16 @@ void rip_enable_apply(struct interface *ifp)
|
||||
}
|
||||
|
||||
/* Apply network configuration to all interface. */
|
||||
void rip_enable_apply_all(void)
|
||||
static void rip_enable_apply_all(struct rip *rip)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
|
||||
/* Check each interface. */
|
||||
FOR_ALL_INTERFACES (vrf, ifp)
|
||||
FOR_ALL_INTERFACES (rip->vrf, ifp)
|
||||
rip_enable_apply(ifp);
|
||||
}
|
||||
|
||||
int rip_neighbor_lookup(struct sockaddr_in *from)
|
||||
int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from)
|
||||
{
|
||||
struct prefix_ipv4 p;
|
||||
struct route_node *node;
|
||||
@ -991,7 +1017,7 @@ int rip_neighbor_lookup(struct sockaddr_in *from)
|
||||
}
|
||||
|
||||
/* Add new RIP neighbor to the neighbor tree. */
|
||||
int rip_neighbor_add(struct prefix_ipv4 *p)
|
||||
int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p)
|
||||
{
|
||||
struct route_node *node;
|
||||
|
||||
@ -1006,7 +1032,7 @@ int rip_neighbor_add(struct prefix_ipv4 *p)
|
||||
}
|
||||
|
||||
/* Delete RIP neighbor from the neighbor tree. */
|
||||
int rip_neighbor_delete(struct prefix_ipv4 *p)
|
||||
int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p)
|
||||
{
|
||||
struct route_node *node;
|
||||
|
||||
@ -1027,50 +1053,51 @@ int rip_neighbor_delete(struct prefix_ipv4 *p)
|
||||
}
|
||||
|
||||
/* Clear all network and neighbor configuration. */
|
||||
void rip_clean_network(void)
|
||||
void rip_clean_network(struct rip *rip)
|
||||
{
|
||||
unsigned int i;
|
||||
char *str;
|
||||
struct route_node *rn;
|
||||
|
||||
/* rip_enable_network. */
|
||||
for (rn = route_top(rip_enable_network); rn; rn = route_next(rn))
|
||||
/* rip->enable_network. */
|
||||
for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
|
||||
if (rn->info) {
|
||||
rn->info = NULL;
|
||||
route_unlock_node(rn);
|
||||
}
|
||||
|
||||
/* rip_enable_interface. */
|
||||
for (i = 0; i < vector_active(rip_enable_interface); i++)
|
||||
if ((str = vector_slot(rip_enable_interface, i)) != NULL) {
|
||||
/* rip->enable_interface. */
|
||||
for (i = 0; i < vector_active(rip->enable_interface); i++)
|
||||
if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
|
||||
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
|
||||
vector_slot(rip_enable_interface, i) = NULL;
|
||||
vector_slot(rip->enable_interface, i) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility function for looking up passive interface settings. */
|
||||
static int rip_passive_nondefault_lookup(const char *ifname)
|
||||
static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
|
||||
{
|
||||
unsigned int i;
|
||||
char *str;
|
||||
|
||||
for (i = 0; i < vector_active(Vrip_passive_nondefault); i++)
|
||||
if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL)
|
||||
for (i = 0; i < vector_active(rip->passive_nondefault); i++)
|
||||
if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
|
||||
if (strcmp(str, ifname) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void rip_passive_interface_apply(struct interface *ifp)
|
||||
static void rip_passive_interface_apply(struct interface *ifp)
|
||||
{
|
||||
struct rip *rip;
|
||||
struct rip_interface *ri;
|
||||
|
||||
ri = ifp->info;
|
||||
rip = ri->rip;
|
||||
if (rip == NULL)
|
||||
return;
|
||||
|
||||
ri = ifp->info;
|
||||
|
||||
ri->passive = ((rip_passive_nondefault_lookup(ifp->name) < 0)
|
||||
ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
|
||||
? rip->passive_default
|
||||
: !rip->passive_default);
|
||||
|
||||
@ -1079,39 +1106,38 @@ void rip_passive_interface_apply(struct interface *ifp)
|
||||
ri->passive);
|
||||
}
|
||||
|
||||
static void rip_passive_interface_apply_all(void)
|
||||
static void rip_passive_interface_apply_all(struct rip *rip)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp)
|
||||
FOR_ALL_INTERFACES (rip->vrf, ifp)
|
||||
rip_passive_interface_apply(ifp);
|
||||
}
|
||||
|
||||
/* Passive interface. */
|
||||
int rip_passive_nondefault_set(const char *ifname)
|
||||
int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
|
||||
{
|
||||
if (rip_passive_nondefault_lookup(ifname) >= 0)
|
||||
if (rip_passive_nondefault_lookup(rip, ifname) >= 0)
|
||||
/*
|
||||
* Don't return an error, this can happen after changing
|
||||
* 'passive-default'.
|
||||
*/
|
||||
return NB_OK;
|
||||
|
||||
vector_set(Vrip_passive_nondefault,
|
||||
vector_set(rip->passive_nondefault,
|
||||
XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
|
||||
|
||||
rip_passive_interface_apply_all();
|
||||
rip_passive_interface_apply_all(rip);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int rip_passive_nondefault_unset(const char *ifname)
|
||||
int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
|
||||
{
|
||||
int i;
|
||||
char *str;
|
||||
|
||||
i = rip_passive_nondefault_lookup(ifname);
|
||||
i = rip_passive_nondefault_lookup(rip, ifname);
|
||||
if (i < 0)
|
||||
/*
|
||||
* Don't return an error, this can happen after changing
|
||||
@ -1119,36 +1145,38 @@ int rip_passive_nondefault_unset(const char *ifname)
|
||||
*/
|
||||
return NB_OK;
|
||||
|
||||
str = vector_slot(Vrip_passive_nondefault, i);
|
||||
str = vector_slot(rip->passive_nondefault, i);
|
||||
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
|
||||
vector_unset(Vrip_passive_nondefault, i);
|
||||
vector_unset(rip->passive_nondefault, i);
|
||||
|
||||
rip_passive_interface_apply_all();
|
||||
rip_passive_interface_apply_all(rip);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/* Free all configured RIP passive-interface settings. */
|
||||
void rip_passive_nondefault_clean(void)
|
||||
void rip_passive_nondefault_clean(struct rip *rip)
|
||||
{
|
||||
unsigned int i;
|
||||
char *str;
|
||||
|
||||
for (i = 0; i < vector_active(Vrip_passive_nondefault); i++)
|
||||
if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) {
|
||||
for (i = 0; i < vector_active(rip->passive_nondefault); i++)
|
||||
if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
|
||||
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
|
||||
vector_slot(Vrip_passive_nondefault, i) = NULL;
|
||||
vector_slot(rip->passive_nondefault, i) = NULL;
|
||||
}
|
||||
rip_passive_interface_apply_all();
|
||||
rip_passive_interface_apply_all(rip);
|
||||
}
|
||||
|
||||
/* Write rip configuration of each interface. */
|
||||
static int rip_interface_config_write(struct vty *vty)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
struct vrf *vrf;
|
||||
int write = 0;
|
||||
|
||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||
struct interface *ifp;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
struct lyd_node *dnode;
|
||||
|
||||
@ -1162,18 +1190,19 @@ static int rip_interface_config_write(struct vty *vty)
|
||||
write = 1;
|
||||
nb_cli_show_dnode_cmds(vty, dnode, false);
|
||||
}
|
||||
}
|
||||
|
||||
return write;
|
||||
}
|
||||
|
||||
int rip_show_network_config(struct vty *vty)
|
||||
int rip_show_network_config(struct vty *vty, struct rip *rip)
|
||||
{
|
||||
unsigned int i;
|
||||
char *ifname;
|
||||
struct route_node *node;
|
||||
|
||||
/* Network type RIP enable interface statement. */
|
||||
for (node = route_top(rip_enable_network); node;
|
||||
for (node = route_top(rip->enable_network); node;
|
||||
node = route_next(node))
|
||||
if (node->info)
|
||||
vty_out(vty, " %s/%u\n",
|
||||
@ -1181,8 +1210,8 @@ int rip_show_network_config(struct vty *vty)
|
||||
node->p.prefixlen);
|
||||
|
||||
/* Interface name RIP enable statement. */
|
||||
for (i = 0; i < vector_active(rip_enable_interface); i++)
|
||||
if ((ifname = vector_slot(rip_enable_interface, i)) != NULL)
|
||||
for (i = 0; i < vector_active(rip->enable_interface); i++)
|
||||
if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
|
||||
vty_out(vty, " %s\n", ifname);
|
||||
|
||||
/* RIP neighbors listing. */
|
||||
@ -1197,10 +1226,26 @@ static struct cmd_node interface_node = {
|
||||
INTERFACE_NODE, "%s(config-if)# ", 1,
|
||||
};
|
||||
|
||||
void rip_interface_sync(struct interface *ifp)
|
||||
{
|
||||
struct vrf *vrf;
|
||||
|
||||
vrf = vrf_lookup_by_id(ifp->vrf_id);
|
||||
if (vrf) {
|
||||
struct rip_interface *ri;
|
||||
|
||||
ri = ifp->info;
|
||||
if (ri)
|
||||
ri->rip = vrf->info;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when interface structure allocated. */
|
||||
static int rip_interface_new_hook(struct interface *ifp)
|
||||
{
|
||||
ifp->info = rip_interface_new();
|
||||
rip_interface_sync(ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1220,13 +1265,6 @@ void rip_if_init(void)
|
||||
hook_register_prio(if_add, 0, rip_interface_new_hook);
|
||||
hook_register_prio(if_del, 0, rip_interface_delete_hook);
|
||||
|
||||
/* RIP network init. */
|
||||
rip_enable_interface = vector_init(1);
|
||||
rip_enable_network = route_table_init();
|
||||
|
||||
/* RIP passive interface. */
|
||||
Vrip_passive_nondefault = vector_init(1);
|
||||
|
||||
/* Install interface node. */
|
||||
install_node(&interface_node, rip_interface_config_write);
|
||||
if_cmd_init();
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef _QUAGGA_RIP_INTERFACE_H
|
||||
#define _QUAGGA_RIP_INTERFACE_H
|
||||
|
||||
#include "zclient.h"
|
||||
|
||||
extern int rip_interface_down(int, struct zclient *, zebra_size_t, vrf_id_t);
|
||||
extern int rip_interface_up(int, struct zclient *, zebra_size_t, vrf_id_t);
|
||||
extern int rip_interface_add(int, struct zclient *, zebra_size_t, vrf_id_t);
|
||||
@ -28,5 +30,8 @@ extern int rip_interface_address_add(int, struct zclient *, zebra_size_t,
|
||||
vrf_id_t);
|
||||
extern int rip_interface_address_delete(int, struct zclient *, zebra_size_t,
|
||||
vrf_id_t);
|
||||
extern int rip_interface_vrf_update(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id);
|
||||
extern void rip_interface_sync(struct interface *ifp);
|
||||
|
||||
#endif /* _QUAGGA_RIP_INTERFACE_H */
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "sigevent.h"
|
||||
#include "zclient.h"
|
||||
#include "vrf.h"
|
||||
#include "if_rmap.h"
|
||||
#include "libfrr.h"
|
||||
|
||||
#include "ripd/ripd.h"
|
||||
@ -46,7 +47,7 @@
|
||||
static struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}};
|
||||
|
||||
/* ripd privileges */
|
||||
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
|
||||
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN};
|
||||
|
||||
struct zebra_privs_t ripd_privs = {
|
||||
#if defined(FRR_USER)
|
||||
@ -59,7 +60,7 @@ struct zebra_privs_t ripd_privs = {
|
||||
.vty_group = VTY_GROUP,
|
||||
#endif
|
||||
.caps_p = _caps_p,
|
||||
.cap_num_p = 2,
|
||||
.cap_num_p = array_size(_caps_p),
|
||||
.cap_num_i = 0};
|
||||
|
||||
/* Master of threads. */
|
||||
@ -81,8 +82,8 @@ static void sigint(void)
|
||||
{
|
||||
zlog_notice("Terminating on signal");
|
||||
|
||||
rip_clean();
|
||||
|
||||
rip_vrf_terminate();
|
||||
if_rmap_terminate();
|
||||
rip_zclient_stop();
|
||||
frr_fini();
|
||||
|
||||
@ -171,14 +172,13 @@ int main(int argc, char **argv)
|
||||
/* Library initialization. */
|
||||
rip_error_init();
|
||||
keychain_init();
|
||||
vrf_init(NULL, NULL, NULL, NULL, NULL);
|
||||
rip_vrf_init();
|
||||
|
||||
/* RIP related initialization. */
|
||||
rip_init();
|
||||
rip_if_init();
|
||||
rip_cli_init();
|
||||
rip_zclient_init(master);
|
||||
rip_peer_init();
|
||||
|
||||
frr_config_fork();
|
||||
frr_run(master);
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
DEFINE_MGROUP(RIPD, "ripd")
|
||||
DEFINE_MTYPE(RIPD, RIP, "RIP structure")
|
||||
DEFINE_MTYPE(RIPD, RIP_VRF_NAME, "RIP VRF name")
|
||||
DEFINE_MTYPE(RIPD, RIP_INFO, "RIP route info")
|
||||
DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface")
|
||||
DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String")
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
DECLARE_MGROUP(RIPD)
|
||||
DECLARE_MTYPE(RIP)
|
||||
DECLARE_MTYPE(RIP_VRF_NAME)
|
||||
DECLARE_MTYPE(RIP_INFO)
|
||||
DECLARE_MTYPE(RIP_INTERFACE)
|
||||
DECLARE_MTYPE(RIP_INTERFACE_STRING)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,28 +29,27 @@
|
||||
|
||||
#include "ripd/ripd.h"
|
||||
|
||||
static struct list *rip_offset_list_master;
|
||||
|
||||
#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name)
|
||||
#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_IN].metric)
|
||||
|
||||
#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name)
|
||||
#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric)
|
||||
|
||||
struct rip_offset_list *rip_offset_list_new(const char *ifname)
|
||||
struct rip_offset_list *rip_offset_list_new(struct rip *rip, const char *ifname)
|
||||
{
|
||||
struct rip_offset_list *offset;
|
||||
|
||||
offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list));
|
||||
offset->rip = rip;
|
||||
offset->ifname = strdup(ifname);
|
||||
listnode_add_sort(rip_offset_list_master, offset);
|
||||
listnode_add_sort(rip->offset_list_master, offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void offset_list_del(struct rip_offset_list *offset)
|
||||
{
|
||||
listnode_delete(rip_offset_list_master, offset);
|
||||
listnode_delete(offset->rip->offset_list_master, offset);
|
||||
if (OFFSET_LIST_IN_NAME(offset))
|
||||
free(OFFSET_LIST_IN_NAME(offset));
|
||||
if (OFFSET_LIST_OUT_NAME(offset))
|
||||
@ -59,12 +58,13 @@ void offset_list_del(struct rip_offset_list *offset)
|
||||
XFREE(MTYPE_RIP_OFFSET_LIST, offset);
|
||||
}
|
||||
|
||||
struct rip_offset_list *rip_offset_list_lookup(const char *ifname)
|
||||
struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
|
||||
const char *ifname)
|
||||
{
|
||||
struct rip_offset_list *offset;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) {
|
||||
for (ALL_LIST_ELEMENTS(rip->offset_list_master, node, nnode, offset)) {
|
||||
if (strcmp(offset->ifname, ifname) == 0)
|
||||
return offset;
|
||||
}
|
||||
@ -75,11 +75,12 @@ struct rip_offset_list *rip_offset_list_lookup(const char *ifname)
|
||||
int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
|
||||
uint32_t *metric)
|
||||
{
|
||||
struct rip_interface *ri = ifp->info;
|
||||
struct rip_offset_list *offset;
|
||||
struct access_list *alist;
|
||||
|
||||
/* Look up offset-list with interface name. */
|
||||
offset = rip_offset_list_lookup(ifp->name);
|
||||
offset = rip_offset_list_lookup(ri->rip, ifp->name);
|
||||
if (offset && OFFSET_LIST_IN_NAME(offset)) {
|
||||
alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
|
||||
|
||||
@ -92,7 +93,7 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
|
||||
return 0;
|
||||
}
|
||||
/* Look up offset-list without interface name. */
|
||||
offset = rip_offset_list_lookup("*");
|
||||
offset = rip_offset_list_lookup(ri->rip, "*");
|
||||
if (offset && OFFSET_LIST_IN_NAME(offset)) {
|
||||
alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
|
||||
|
||||
@ -111,11 +112,12 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
|
||||
int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
|
||||
uint32_t *metric)
|
||||
{
|
||||
struct rip_interface *ri = ifp->info;
|
||||
struct rip_offset_list *offset;
|
||||
struct access_list *alist;
|
||||
|
||||
/* Look up offset-list with interface name. */
|
||||
offset = rip_offset_list_lookup(ifp->name);
|
||||
offset = rip_offset_list_lookup(ri->rip, ifp->name);
|
||||
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
|
||||
alist = access_list_lookup(AFI_IP,
|
||||
OFFSET_LIST_OUT_NAME(offset));
|
||||
@ -130,7 +132,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
|
||||
}
|
||||
|
||||
/* Look up offset-list without interface name. */
|
||||
offset = rip_offset_list_lookup("*");
|
||||
offset = rip_offset_list_lookup(ri->rip, "*");
|
||||
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
|
||||
alist = access_list_lookup(AFI_IP,
|
||||
OFFSET_LIST_OUT_NAME(offset));
|
||||
@ -146,24 +148,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int offset_list_cmp(struct rip_offset_list *o1,
|
||||
struct rip_offset_list *o2)
|
||||
int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2)
|
||||
{
|
||||
return strcmp(o1->ifname, o2->ifname);
|
||||
}
|
||||
|
||||
void rip_offset_init(void)
|
||||
{
|
||||
rip_offset_list_master = list_new();
|
||||
rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
|
||||
rip_offset_list_master->del = (void (*)(void *))offset_list_del;
|
||||
}
|
||||
|
||||
void rip_offset_clean(void)
|
||||
{
|
||||
list_delete(&rip_offset_list_master);
|
||||
|
||||
rip_offset_list_master = list_new();
|
||||
rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
|
||||
rip_offset_list_master->del = (void (*)(void *))offset_list_del;
|
||||
}
|
||||
|
@ -29,9 +29,6 @@
|
||||
|
||||
#include "ripd/ripd.h"
|
||||
|
||||
/* Linked list of RIP peer. */
|
||||
struct list *peer_list;
|
||||
|
||||
static struct rip_peer *rip_peer_new(void)
|
||||
{
|
||||
return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer));
|
||||
@ -39,27 +36,28 @@ static struct rip_peer *rip_peer_new(void)
|
||||
|
||||
static void rip_peer_free(struct rip_peer *peer)
|
||||
{
|
||||
RIP_TIMER_OFF(peer->t_timeout);
|
||||
XFREE(MTYPE_RIP_PEER, peer);
|
||||
}
|
||||
|
||||
struct rip_peer *rip_peer_lookup(struct in_addr *addr)
|
||||
struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr)
|
||||
{
|
||||
struct rip_peer *peer;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
|
||||
for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
|
||||
if (IPV4_ADDR_SAME(&peer->addr, addr))
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct rip_peer *rip_peer_lookup_next(struct in_addr *addr)
|
||||
struct rip_peer *rip_peer_lookup_next(struct rip *rip, struct in_addr *addr)
|
||||
{
|
||||
struct rip_peer *peer;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
|
||||
for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
|
||||
if (htonl(peer->addr.s_addr) > htonl(addr->s_addr))
|
||||
return peer;
|
||||
}
|
||||
@ -72,26 +70,27 @@ static int rip_peer_timeout(struct thread *t)
|
||||
struct rip_peer *peer;
|
||||
|
||||
peer = THREAD_ARG(t);
|
||||
listnode_delete(peer_list, peer);
|
||||
listnode_delete(peer->rip->peer_list, peer);
|
||||
rip_peer_free(peer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get RIP peer. At the same time update timeout thread. */
|
||||
static struct rip_peer *rip_peer_get(struct in_addr *addr)
|
||||
static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr)
|
||||
{
|
||||
struct rip_peer *peer;
|
||||
|
||||
peer = rip_peer_lookup(addr);
|
||||
peer = rip_peer_lookup(rip, addr);
|
||||
|
||||
if (peer) {
|
||||
if (peer->t_timeout)
|
||||
thread_cancel(peer->t_timeout);
|
||||
} else {
|
||||
peer = rip_peer_new();
|
||||
peer->rip = rip;
|
||||
peer->addr = *addr;
|
||||
listnode_add_sort(peer_list, peer);
|
||||
listnode_add_sort(rip->peer_list, peer);
|
||||
}
|
||||
|
||||
/* Update timeout thread. */
|
||||
@ -105,24 +104,24 @@ static struct rip_peer *rip_peer_get(struct in_addr *addr)
|
||||
return peer;
|
||||
}
|
||||
|
||||
void rip_peer_update(struct sockaddr_in *from, uint8_t version)
|
||||
void rip_peer_update(struct rip *rip, struct sockaddr_in *from, uint8_t version)
|
||||
{
|
||||
struct rip_peer *peer;
|
||||
peer = rip_peer_get(&from->sin_addr);
|
||||
peer = rip_peer_get(rip, &from->sin_addr);
|
||||
peer->version = version;
|
||||
}
|
||||
|
||||
void rip_peer_bad_route(struct sockaddr_in *from)
|
||||
void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from)
|
||||
{
|
||||
struct rip_peer *peer;
|
||||
peer = rip_peer_get(&from->sin_addr);
|
||||
peer = rip_peer_get(rip, &from->sin_addr);
|
||||
peer->recv_badroutes++;
|
||||
}
|
||||
|
||||
void rip_peer_bad_packet(struct sockaddr_in *from)
|
||||
void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from)
|
||||
{
|
||||
struct rip_peer *peer;
|
||||
peer = rip_peer_get(&from->sin_addr);
|
||||
peer = rip_peer_get(rip, &from->sin_addr);
|
||||
peer->recv_badpackets++;
|
||||
}
|
||||
|
||||
@ -155,14 +154,14 @@ static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len)
|
||||
return buf;
|
||||
}
|
||||
|
||||
void rip_peer_display(struct vty *vty)
|
||||
void rip_peer_display(struct vty *vty, struct rip *rip)
|
||||
{
|
||||
struct rip_peer *peer;
|
||||
struct listnode *node, *nnode;
|
||||
#define RIP_UPTIME_LEN 25
|
||||
char timebuf[RIP_UPTIME_LEN];
|
||||
|
||||
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
|
||||
for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
|
||||
vty_out(vty, " %-16s %9d %9d %9d %s\n",
|
||||
inet_ntoa(peer->addr), peer->recv_badpackets,
|
||||
peer->recv_badroutes, ZEBRA_RIP_DISTANCE_DEFAULT,
|
||||
@ -170,7 +169,7 @@ void rip_peer_display(struct vty *vty)
|
||||
}
|
||||
}
|
||||
|
||||
static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
|
||||
int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
|
||||
{
|
||||
if (p2->addr.s_addr == p1->addr.s_addr)
|
||||
return 0;
|
||||
@ -178,8 +177,7 @@ static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
|
||||
return (htonl(p1->addr.s_addr) < htonl(p2->addr.s_addr)) ? -1 : 1;
|
||||
}
|
||||
|
||||
void rip_peer_init(void)
|
||||
void rip_peer_list_del(void *arg)
|
||||
{
|
||||
peer_list = list_new();
|
||||
peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp;
|
||||
rip_peer_free(arg);
|
||||
}
|
||||
|
@ -156,17 +156,23 @@ static uint8_t *rip2Globals(struct variable *v, oid name[], size_t *length,
|
||||
int exact, size_t *var_len,
|
||||
WriteMethod **write_method)
|
||||
{
|
||||
struct rip *rip;
|
||||
|
||||
if (smux_header_generic(v, name, length, exact, var_len, write_method)
|
||||
== MATCH_FAILED)
|
||||
return NULL;
|
||||
|
||||
rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
|
||||
if (!rip)
|
||||
return NULL;
|
||||
|
||||
/* Retrun global counter. */
|
||||
switch (v->magic) {
|
||||
case RIP2GLOBALROUTECHANGES:
|
||||
return SNMP_INTEGER(rip_global_route_changes);
|
||||
return SNMP_INTEGER(rip->counters.route_changes);
|
||||
break;
|
||||
case RIP2GLOBALQUERIES:
|
||||
return SNMP_INTEGER(rip_global_queries);
|
||||
return SNMP_INTEGER(rip->counters.queries);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
@ -281,9 +287,14 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
|
||||
size_t *length, struct in_addr *addr,
|
||||
int exact)
|
||||
{
|
||||
struct rip *rip;
|
||||
int len;
|
||||
struct rip_peer *peer;
|
||||
|
||||
rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
|
||||
if (!rip)
|
||||
return NULL;
|
||||
|
||||
if (exact) {
|
||||
/* Check the length. */
|
||||
if (*length - v->namelen != sizeof(struct in_addr) + 1)
|
||||
@ -291,7 +302,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
|
||||
|
||||
oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr);
|
||||
|
||||
peer = rip_peer_lookup(addr);
|
||||
peer = rip_peer_lookup(rip, addr);
|
||||
|
||||
if (peer->domain
|
||||
== (int)name[v->namelen + sizeof(struct in_addr)])
|
||||
@ -306,7 +317,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
|
||||
oid2in_addr(name + v->namelen, len, addr);
|
||||
|
||||
len = *length - v->namelen;
|
||||
peer = rip_peer_lookup(addr);
|
||||
peer = rip_peer_lookup(rip, addr);
|
||||
if (peer) {
|
||||
if ((len < (int)sizeof(struct in_addr) + 1)
|
||||
|| (peer->domain
|
||||
@ -321,7 +332,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
|
||||
return peer;
|
||||
}
|
||||
}
|
||||
peer = rip_peer_lookup_next(addr);
|
||||
peer = rip_peer_lookup_next(rip, addr);
|
||||
|
||||
if (!peer)
|
||||
return NULL;
|
||||
@ -402,10 +413,10 @@ static long rip2IfConfSend(struct rip_interface *ri)
|
||||
return ripVersion2;
|
||||
else if (ri->ri_send & RIPv1)
|
||||
return ripVersion1;
|
||||
else if (rip) {
|
||||
if (rip->version_send == RIPv2)
|
||||
else if (ri->rip) {
|
||||
if (ri->rip->version_send == RIPv2)
|
||||
return ripVersion2;
|
||||
else if (rip->version_send == RIPv1)
|
||||
else if (ri->rip->version_send == RIPv1)
|
||||
return ripVersion1;
|
||||
}
|
||||
return doNotSend;
|
||||
@ -423,7 +434,7 @@ static long rip2IfConfReceive(struct rip_interface *ri)
|
||||
if (!ri->running)
|
||||
return doNotReceive;
|
||||
|
||||
recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv
|
||||
recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? ri->rip->version_recv
|
||||
: ri->ri_receive;
|
||||
if (recvv == RI_RIP_VERSION_1_AND_2)
|
||||
return rip1OrRip2;
|
||||
|
@ -36,7 +36,8 @@
|
||||
struct zclient *zclient = NULL;
|
||||
|
||||
/* Send ECMP routes to zebra. */
|
||||
static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
|
||||
static void rip_zebra_ipv4_send(struct rip *rip, struct route_node *rp,
|
||||
uint8_t cmd)
|
||||
{
|
||||
struct list *list = (struct list *)rp->info;
|
||||
struct zapi_route api;
|
||||
@ -46,7 +47,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
|
||||
int count = 0;
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.vrf_id = rip->vrf->vrf_id;
|
||||
api.type = ZEBRA_ROUTE_RIP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
|
||||
@ -55,7 +56,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
|
||||
if (count >= MULTIPATH_NUM)
|
||||
break;
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
api_nh->vrf_id = rip->vrf->vrf_id;
|
||||
api_nh->gate = rinfo->nh.gate;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||
if (cmd == ZEBRA_ROUTE_ADD)
|
||||
@ -101,28 +102,30 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
|
||||
inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen);
|
||||
}
|
||||
|
||||
rip_global_route_changes++;
|
||||
rip->counters.route_changes++;
|
||||
}
|
||||
|
||||
/* Add/update ECMP routes to zebra. */
|
||||
void rip_zebra_ipv4_add(struct route_node *rp)
|
||||
void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp)
|
||||
{
|
||||
rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD);
|
||||
rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_ADD);
|
||||
}
|
||||
|
||||
/* Delete ECMP routes from zebra. */
|
||||
void rip_zebra_ipv4_delete(struct route_node *rp)
|
||||
void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp)
|
||||
{
|
||||
rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE);
|
||||
rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_DELETE);
|
||||
}
|
||||
|
||||
/* Zebra route add and delete treatment. */
|
||||
static int rip_zebra_read_route(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct rip *rip;
|
||||
struct zapi_route api;
|
||||
struct nexthop nh;
|
||||
|
||||
rip = rip_lookup_by_vrf_id(vrf_id);
|
||||
if (!rip)
|
||||
return 0;
|
||||
|
||||
@ -136,68 +139,95 @@ static int rip_zebra_read_route(int command, struct zclient *zclient,
|
||||
|
||||
/* Then fetch IPv4 prefixes. */
|
||||
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
|
||||
rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
|
||||
rip_redistribute_add(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
|
||||
(struct prefix_ipv4 *)&api.prefix, &nh,
|
||||
api.metric, api.distance, api.tag);
|
||||
else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
|
||||
rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
|
||||
rip_redistribute_delete(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
|
||||
(struct prefix_ipv4 *)&api.prefix,
|
||||
nh.ifindex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rip_redistribute_conf_update(int type)
|
||||
void rip_redistribute_conf_update(struct rip *rip, int type)
|
||||
{
|
||||
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,
|
||||
0, VRF_DEFAULT);
|
||||
0, rip->vrf->vrf_id);
|
||||
}
|
||||
|
||||
void rip_redistribute_conf_delete(int type)
|
||||
void rip_redistribute_conf_delete(struct rip *rip, int type)
|
||||
{
|
||||
if (zclient->sock > 0)
|
||||
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
|
||||
AFI_IP, type, 0, VRF_DEFAULT);
|
||||
AFI_IP, type, 0, rip->vrf->vrf_id);
|
||||
|
||||
/* Remove the routes from RIP table. */
|
||||
rip_redistribute_withdraw(type);
|
||||
rip_redistribute_withdraw(rip, type);
|
||||
}
|
||||
|
||||
int rip_redistribute_check(int type)
|
||||
int rip_redistribute_check(struct rip *rip, int type)
|
||||
{
|
||||
return vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT);
|
||||
return rip->redist[type].enabled;
|
||||
}
|
||||
|
||||
void rip_redistribute_clean(void)
|
||||
void rip_redistribute_enable(struct rip *rip)
|
||||
{
|
||||
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], VRF_DEFAULT))
|
||||
if (!rip_redistribute_check(rip, i))
|
||||
continue;
|
||||
|
||||
if (zclient->sock > 0)
|
||||
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
|
||||
zclient, AFI_IP, i, 0,
|
||||
VRF_DEFAULT);
|
||||
|
||||
vrf_bitmap_unset(zclient->redist[AFI_IP][i], VRF_DEFAULT);
|
||||
|
||||
/* Remove the routes from RIP table. */
|
||||
rip_redistribute_withdraw(i);
|
||||
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
|
||||
i, 0, rip->vrf->vrf_id);
|
||||
}
|
||||
}
|
||||
|
||||
void rip_show_redistribute_config(struct vty *vty)
|
||||
void rip_redistribute_disable(struct rip *rip)
|
||||
{
|
||||
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (!rip_redistribute_check(rip, i))
|
||||
continue;
|
||||
|
||||
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
|
||||
AFI_IP, i, 0, rip->vrf->vrf_id);
|
||||
}
|
||||
}
|
||||
|
||||
void rip_show_redistribute_config(struct vty *vty, struct rip *rip)
|
||||
{
|
||||
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (i == zclient->redist_default
|
||||
|| !vrf_bitmap_check(zclient->redist[AFI_IP][i],
|
||||
VRF_DEFAULT))
|
||||
|| !rip_redistribute_check(rip, i))
|
||||
continue;
|
||||
|
||||
vty_out(vty, " %s", zebra_route_string(i));
|
||||
}
|
||||
}
|
||||
|
||||
void rip_zebra_vrf_register(struct vrf *vrf)
|
||||
{
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
return;
|
||||
|
||||
if (IS_RIP_DEBUG_EVENT)
|
||||
zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
|
||||
vrf->name, vrf->vrf_id);
|
||||
|
||||
zclient_send_reg_requests(zclient, vrf->vrf_id);
|
||||
}
|
||||
|
||||
void rip_zebra_vrf_deregister(struct vrf *vrf)
|
||||
{
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
return;
|
||||
|
||||
if (IS_RIP_DEBUG_EVENT)
|
||||
zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
|
||||
vrf->name, vrf->vrf_id);
|
||||
|
||||
zclient_send_dereg_requests(zclient, vrf->vrf_id);
|
||||
}
|
||||
|
||||
static void rip_zebra_connected(struct zclient *zclient)
|
||||
{
|
||||
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
||||
@ -215,6 +245,7 @@ void rip_zclient_init(struct thread_master *master)
|
||||
zclient->interface_address_delete = rip_interface_address_delete;
|
||||
zclient->interface_up = rip_interface_up;
|
||||
zclient->interface_down = rip_interface_down;
|
||||
zclient->interface_vrf_update = rip_interface_vrf_update;
|
||||
zclient->redistribute_route_add = rip_zebra_read_route;
|
||||
zclient->redistribute_route_del = rip_zebra_read_route;
|
||||
}
|
||||
|
878
ripd/ripd.c
878
ripd/ripd.c
File diff suppressed because it is too large
Load Diff
186
ripd/ripd.h
186
ripd/ripd.h
@ -99,6 +99,17 @@
|
||||
|
||||
/* RIP structure. */
|
||||
struct rip {
|
||||
RB_ENTRY(rip) entry;
|
||||
|
||||
/* VRF this routing instance is associated with. */
|
||||
char *vrf_name;
|
||||
|
||||
/* VRF backpointer (might be NULL if the VRF doesn't exist). */
|
||||
struct vrf *vrf;
|
||||
|
||||
/* Status of the routing instance. */
|
||||
bool enabled;
|
||||
|
||||
/* RIP socket. */
|
||||
int sock;
|
||||
|
||||
@ -112,9 +123,12 @@ struct rip {
|
||||
/* RIP routing information base. */
|
||||
struct route_table *table;
|
||||
|
||||
/* RIP neighbor. */
|
||||
/* RIP static neighbors. */
|
||||
struct route_table *neighbor;
|
||||
|
||||
/* Linked list of RIP peers. */
|
||||
struct list *peer_list;
|
||||
|
||||
/* RIP threads. */
|
||||
struct thread *t_read;
|
||||
|
||||
@ -144,20 +158,46 @@ struct rip {
|
||||
/* Are we in passive-interface default mode? */
|
||||
bool passive_default;
|
||||
|
||||
/* For redistribute route map. */
|
||||
/* RIP enabled interfaces. */
|
||||
vector enable_interface;
|
||||
|
||||
/* RIP enabled networks. */
|
||||
struct route_table *enable_network;
|
||||
|
||||
/* Vector to store passive-interface name. */
|
||||
vector passive_nondefault;
|
||||
|
||||
/* RIP offset-lists. */
|
||||
struct list *offset_list_master;
|
||||
|
||||
/* RIP redistribute configuration. */
|
||||
struct {
|
||||
bool enabled;
|
||||
struct {
|
||||
char *name;
|
||||
struct route_map *map;
|
||||
} route_map;
|
||||
bool metric_config;
|
||||
uint8_t metric;
|
||||
} route_map[ZEBRA_ROUTE_MAX];
|
||||
} redist[ZEBRA_ROUTE_MAX];
|
||||
|
||||
/* For distribute-list container */
|
||||
struct distribute_ctx *distribute_ctx;
|
||||
|
||||
/* For if_rmap container */
|
||||
struct if_rmap_ctx *if_rmap_ctx;
|
||||
|
||||
/* Counters for SNMP. */
|
||||
struct {
|
||||
/* RIP route changes. */
|
||||
long route_changes;
|
||||
|
||||
/* RIP queries. */
|
||||
long queries;
|
||||
} counters;
|
||||
};
|
||||
RB_HEAD(rip_instance_head, rip);
|
||||
RB_PROTOTYPE(rip_instance_head, rip, entry, rip_instance_compare)
|
||||
|
||||
/* RIP routing table entry which belong to rip_packet. */
|
||||
struct rte {
|
||||
@ -225,11 +265,6 @@ struct rip_info {
|
||||
struct route_node *rp;
|
||||
|
||||
uint8_t distance;
|
||||
|
||||
#ifdef NEW_RIP_TABLE
|
||||
struct rip_info *next;
|
||||
struct rip_info *prev;
|
||||
#endif /* NEW_RIP_TABLE */
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@ -240,6 +275,9 @@ typedef enum {
|
||||
|
||||
/* RIP specific interface configuration. */
|
||||
struct rip_interface {
|
||||
/* Parent routing instance. */
|
||||
struct rip *rip;
|
||||
|
||||
/* RIP is enabled on this interface. */
|
||||
int enable_network;
|
||||
int enable_interface;
|
||||
@ -297,6 +335,9 @@ struct rip_interface {
|
||||
|
||||
/* RIP peer information. */
|
||||
struct rip_peer {
|
||||
/* Parent routing instance. */
|
||||
struct rip *rip;
|
||||
|
||||
/* Peer address. */
|
||||
struct in_addr addr;
|
||||
|
||||
@ -369,6 +410,9 @@ enum rip_event {
|
||||
#define RIP_OFFSET_LIST_MAX 2
|
||||
|
||||
struct rip_offset_list {
|
||||
/* Parent routing instance. */
|
||||
struct rip *rip;
|
||||
|
||||
char *ifname;
|
||||
|
||||
struct {
|
||||
@ -380,104 +424,114 @@ struct rip_offset_list {
|
||||
|
||||
/* Prototypes. */
|
||||
extern void rip_init(void);
|
||||
extern void rip_clean(void);
|
||||
extern void rip_clean_network(void);
|
||||
extern void rip_interfaces_clean(void);
|
||||
extern int rip_passive_nondefault_set(const char *ifname);
|
||||
extern int rip_passive_nondefault_unset(const char *ifname);
|
||||
extern void rip_passive_nondefault_clean(void);
|
||||
extern void rip_clean(struct rip *rip);
|
||||
extern void rip_clean_network(struct rip *rip);
|
||||
extern void rip_interfaces_clean(struct rip *rip);
|
||||
extern int rip_passive_nondefault_set(struct rip *rip, const char *ifname);
|
||||
extern int rip_passive_nondefault_unset(struct rip *rip, const char *ifname);
|
||||
extern void rip_passive_nondefault_clean(struct rip *rip);
|
||||
extern void rip_if_init(void);
|
||||
extern void rip_if_down_all(void);
|
||||
extern void rip_route_map_init(void);
|
||||
extern void rip_zebra_vrf_register(struct vrf *vrf);
|
||||
extern void rip_zebra_vrf_deregister(struct vrf *vrf);
|
||||
extern void rip_zclient_init(struct thread_master *);
|
||||
extern void rip_zclient_stop(void);
|
||||
extern int if_check_address(struct in_addr addr);
|
||||
extern int rip_create(int socket);
|
||||
extern int if_check_address(struct rip *rip, struct in_addr addr);
|
||||
extern struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id);
|
||||
extern struct rip *rip_lookup_by_vrf_name(const char *vrf_name);
|
||||
extern struct rip *rip_create(const char *vrf_name, struct vrf *vrf,
|
||||
int socket);
|
||||
|
||||
extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t,
|
||||
struct connected *);
|
||||
extern int rip_neighbor_lookup(struct sockaddr_in *);
|
||||
extern int rip_neighbor_add(struct prefix_ipv4 *p);
|
||||
extern int rip_neighbor_delete(struct prefix_ipv4 *p);
|
||||
extern int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from);
|
||||
extern int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p);
|
||||
extern int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p);
|
||||
|
||||
extern int rip_enable_network_add(struct prefix *p);
|
||||
extern int rip_enable_network_delete(struct prefix *p);
|
||||
extern int rip_enable_if_add(const char *ifname);
|
||||
extern int rip_enable_if_delete(const char *ifname);
|
||||
extern int rip_enable_network_add(struct rip *rip, struct prefix *p);
|
||||
extern int rip_enable_network_delete(struct rip *rip, struct prefix *p);
|
||||
extern int rip_enable_if_add(struct rip *rip, const char *ifname);
|
||||
extern int rip_enable_if_delete(struct rip *rip, const char *ifname);
|
||||
|
||||
extern void rip_event(enum rip_event, int);
|
||||
extern void rip_ecmp_disable(void);
|
||||
extern void rip_event(struct rip *rip, enum rip_event event, int sock);
|
||||
extern void rip_ecmp_disable(struct rip *rip);
|
||||
|
||||
extern int rip_create_socket(void);
|
||||
extern int rip_create_socket(struct vrf *vrf);
|
||||
|
||||
extern int rip_redistribute_check(int);
|
||||
extern void rip_redistribute_conf_update(int type);
|
||||
extern void rip_redistribute_conf_delete(int type);
|
||||
extern void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p,
|
||||
struct nexthop *nh, unsigned int metric,
|
||||
unsigned char distance, route_tag_t tag);
|
||||
extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t);
|
||||
extern void rip_redistribute_withdraw(int);
|
||||
extern void rip_zebra_ipv4_add(struct route_node *);
|
||||
extern void rip_zebra_ipv4_delete(struct route_node *);
|
||||
extern int rip_redistribute_check(struct rip *rip, int type);
|
||||
extern void rip_redistribute_conf_update(struct rip *rip, int type);
|
||||
extern void rip_redistribute_conf_delete(struct rip *rip, int type);
|
||||
extern void rip_redistribute_add(struct rip *rip, int type, int sub_type,
|
||||
struct prefix_ipv4 *p, struct nexthop *nh,
|
||||
unsigned int metric, unsigned char distance,
|
||||
route_tag_t tag);
|
||||
extern void rip_redistribute_delete(struct rip *rip, int type, int sub_type,
|
||||
struct prefix_ipv4 *p, ifindex_t ifindex);
|
||||
extern void rip_redistribute_withdraw(struct rip *rip, int type);
|
||||
extern void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp);
|
||||
extern void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp);
|
||||
extern void rip_interface_multicast_set(int, struct connected *);
|
||||
extern void rip_distribute_update_interface(struct interface *);
|
||||
extern void rip_if_rmap_update_interface(struct interface *ifp);
|
||||
extern int rip_show_network_config(struct vty *);
|
||||
extern void rip_show_redistribute_config(struct vty *);
|
||||
|
||||
extern void rip_peer_init(void);
|
||||
extern void rip_peer_update(struct sockaddr_in *, uint8_t);
|
||||
extern void rip_peer_bad_route(struct sockaddr_in *);
|
||||
extern void rip_peer_bad_packet(struct sockaddr_in *);
|
||||
extern void rip_peer_display(struct vty *);
|
||||
extern struct rip_peer *rip_peer_lookup(struct in_addr *);
|
||||
extern struct rip_peer *rip_peer_lookup_next(struct in_addr *);
|
||||
extern int rip_show_network_config(struct vty *vty, struct rip *rip);
|
||||
extern void rip_show_redistribute_config(struct vty *vty, struct rip *rip);
|
||||
|
||||
extern void rip_peer_update(struct rip *rip, struct sockaddr_in *from,
|
||||
uint8_t version);
|
||||
extern void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from);
|
||||
extern void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from);
|
||||
extern void rip_peer_display(struct vty *vty, struct rip *rip);
|
||||
extern struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr);
|
||||
extern struct rip_peer *rip_peer_lookup_next(struct rip *rip,
|
||||
struct in_addr *addr);
|
||||
extern int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2);
|
||||
extern void rip_peer_list_del(void *arg);
|
||||
|
||||
extern void rip_info_free(struct rip_info *);
|
||||
extern struct rip *rip_info_get_instance(const struct rip_info *rinfo);
|
||||
extern struct rip_distance *rip_distance_new(void);
|
||||
extern void rip_distance_free(struct rip_distance *rdistance);
|
||||
extern uint8_t rip_distance_apply(struct rip_info *);
|
||||
extern void rip_redistribute_clean(void);
|
||||
extern uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo);
|
||||
extern void rip_redistribute_enable(struct rip *rip);
|
||||
extern void rip_redistribute_disable(struct rip *rip);
|
||||
|
||||
extern int rip_route_rte(struct rip_info *rinfo);
|
||||
extern struct rip_info *rip_ecmp_add(struct rip_info *);
|
||||
extern struct rip_info *rip_ecmp_replace(struct rip_info *);
|
||||
extern struct rip_info *rip_ecmp_delete(struct rip_info *);
|
||||
extern struct rip_info *rip_ecmp_add(struct rip *rip,
|
||||
struct rip_info *rinfo_new);
|
||||
extern struct rip_info *rip_ecmp_replace(struct rip *rip,
|
||||
struct rip_info *rinfo_new);
|
||||
extern struct rip_info *rip_ecmp_delete(struct rip *rip,
|
||||
struct rip_info *rinfo);
|
||||
|
||||
extern struct rip_offset_list *rip_offset_list_new(const char *ifname);
|
||||
extern struct rip_offset_list *rip_offset_list_new(struct rip *rip,
|
||||
const char *ifname);
|
||||
extern void offset_list_del(struct rip_offset_list *offset);
|
||||
extern struct rip_offset_list *rip_offset_list_lookup(const char *ifname);
|
||||
extern struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
|
||||
const char *ifname);
|
||||
extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *,
|
||||
uint32_t *);
|
||||
extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *,
|
||||
uint32_t *);
|
||||
extern void rip_offset_init(void);
|
||||
extern void rip_offset_clean(void);
|
||||
extern int offset_list_cmp(struct rip_offset_list *o1,
|
||||
struct rip_offset_list *o2);
|
||||
|
||||
extern void rip_vrf_init(void);
|
||||
extern void rip_vrf_terminate(void);
|
||||
|
||||
/* YANG notifications */
|
||||
extern void ripd_notif_send_auth_type_failure(const char *ifname);
|
||||
extern void ripd_notif_send_auth_failure(const char *ifname);
|
||||
|
||||
/* There is only one rip strucutre. */
|
||||
extern struct rip *rip;
|
||||
|
||||
extern struct zebra_privs_t ripd_privs;
|
||||
extern struct rip_instance_head rip_instances;
|
||||
|
||||
/* Master thread strucutre. */
|
||||
extern struct thread_master *master;
|
||||
|
||||
/* RIP statistics for SNMP. */
|
||||
extern long rip_global_route_changes;
|
||||
extern long rip_global_queries;
|
||||
|
||||
DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc))
|
||||
DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc))
|
||||
|
||||
extern struct list *peer_list;
|
||||
extern struct route_table *rip_distance_table;
|
||||
extern vector Vrip_passive_nondefault;
|
||||
|
||||
/* Northbound. */
|
||||
extern void rip_cli_init(void);
|
||||
extern const struct frr_yang_module_info frr_ripd_info;
|
||||
|
@ -39,31 +39,46 @@
|
||||
*/
|
||||
DEFPY_NOSH (router_ripng,
|
||||
router_ripng_cmd,
|
||||
"router ripng",
|
||||
"router ripng [vrf NAME]",
|
||||
"Enable a routing process\n"
|
||||
"Make RIPng instance command\n")
|
||||
"Make RIPng instance command\n"
|
||||
VRF_CMD_HELP_STR)
|
||||
{
|
||||
char xpath[XPATH_MAXLEN];
|
||||
int ret;
|
||||
|
||||
nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_CREATE,
|
||||
NULL);
|
||||
/* Build RIPng instance XPath. */
|
||||
if (!vrf)
|
||||
vrf = VRF_DEFAULT_NAME;
|
||||
snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
|
||||
vrf);
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
|
||||
ret = nb_cli_apply_changes(vty, NULL);
|
||||
if (ret == CMD_SUCCESS)
|
||||
VTY_PUSH_XPATH(RIPNG_NODE, "/frr-ripngd:ripngd/instance");
|
||||
VTY_PUSH_XPATH(RIPNG_NODE, xpath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFPY (no_router_ripng,
|
||||
no_router_ripng_cmd,
|
||||
"no router ripng",
|
||||
"no router ripng [vrf NAME]",
|
||||
NO_STR
|
||||
"Enable a routing process\n"
|
||||
"Make RIPng instance command\n")
|
||||
"Make RIPng instance command\n"
|
||||
VRF_CMD_HELP_STR)
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_DESTROY,
|
||||
NULL);
|
||||
char xpath[XPATH_MAXLEN];
|
||||
|
||||
/* Build RIPng instance XPath. */
|
||||
if (!vrf)
|
||||
vrf = VRF_DEFAULT_NAME;
|
||||
snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
|
||||
vrf);
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
@ -71,8 +86,15 @@ DEFPY (no_router_ripng,
|
||||
void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
|
||||
bool show_defaults)
|
||||
{
|
||||
const char *vrf_name;
|
||||
|
||||
vrf_name = yang_dnode_get_string(dnode, "./vrf");
|
||||
|
||||
vty_out(vty, "!\n");
|
||||
vty_out(vty, "router ripng\n");
|
||||
vty_out(vty, "router ripng");
|
||||
if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
|
||||
vty_out(vty, " vrf %s", vrf_name);
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -456,12 +478,24 @@ void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode,
|
||||
*/
|
||||
DEFPY (clear_ipv6_rip,
|
||||
clear_ipv6_rip_cmd,
|
||||
"clear ipv6 ripng",
|
||||
"clear ipv6 ripng [vrf WORD]",
|
||||
CLEAR_STR
|
||||
IPV6_STR
|
||||
"Clear IPv6 RIP database\n")
|
||||
"Clear IPv6 RIP database\n"
|
||||
VRF_CMD_HELP_STR)
|
||||
{
|
||||
return nb_cli_rpc("/frr-ripngd:clear-ripng-route", NULL, NULL);
|
||||
struct list *input;
|
||||
|
||||
input = list_new();
|
||||
if (vrf) {
|
||||
struct yang_data *yang_vrf;
|
||||
|
||||
yang_vrf = yang_data_new(
|
||||
"/frr-ripngd:clear-ripng-route/input/vrf", vrf);
|
||||
listnode_add(input, yang_vrf);
|
||||
}
|
||||
|
||||
return nb_cli_rpc("/frr-ripngd:clear-ripng-route", input, NULL);
|
||||
}
|
||||
|
||||
void ripng_cli_init(void)
|
||||
|
@ -52,12 +52,12 @@
|
||||
/* Static utility function. */
|
||||
static void ripng_enable_apply(struct interface *);
|
||||
static void ripng_passive_interface_apply(struct interface *);
|
||||
static int ripng_enable_if_lookup(const char *);
|
||||
static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname);
|
||||
static int ripng_enable_network_lookup2(struct connected *);
|
||||
static void ripng_enable_apply_all(void);
|
||||
static void ripng_enable_apply_all(struct ripng *ripng);
|
||||
|
||||
/* Join to the all rip routers multicast group. */
|
||||
static int ripng_multicast_join(struct interface *ifp)
|
||||
static int ripng_multicast_join(struct interface *ifp, int sock)
|
||||
{
|
||||
int ret;
|
||||
struct ipv6_mreq mreq;
|
||||
@ -75,8 +75,7 @@ static int ripng_multicast_join(struct interface *ifp)
|
||||
*/
|
||||
frr_elevate_privs(&ripngd_privs) {
|
||||
|
||||
ret = setsockopt(ripng->sock, IPPROTO_IPV6,
|
||||
IPV6_JOIN_GROUP,
|
||||
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
(char *)&mreq, sizeof(mreq));
|
||||
save_errno = errno;
|
||||
|
||||
@ -111,7 +110,7 @@ static int ripng_multicast_join(struct interface *ifp)
|
||||
}
|
||||
|
||||
/* Leave from the all rip routers multicast group. */
|
||||
static int ripng_multicast_leave(struct interface *ifp)
|
||||
static int ripng_multicast_leave(struct interface *ifp, int sock)
|
||||
{
|
||||
int ret;
|
||||
struct ipv6_mreq mreq;
|
||||
@ -121,7 +120,7 @@ static int ripng_multicast_leave(struct interface *ifp)
|
||||
inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
|
||||
mreq.ipv6mr_interface = ifp->ifindex;
|
||||
|
||||
ret = setsockopt(ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
|
||||
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
|
||||
(char *)&mreq, sizeof(mreq));
|
||||
if (ret < 0)
|
||||
zlog_warn("can't setsockopt IPV6_LEAVE_GROUP: %s",
|
||||
@ -163,9 +162,13 @@ static int ripng_if_down(struct interface *ifp)
|
||||
struct agg_node *rp;
|
||||
struct ripng_info *rinfo;
|
||||
struct ripng_interface *ri;
|
||||
struct ripng *ripng;
|
||||
struct list *list = NULL;
|
||||
struct listnode *listnode = NULL, *nextnode = NULL;
|
||||
|
||||
ri = ifp->info;
|
||||
ripng = ri->ripng;
|
||||
|
||||
if (ripng)
|
||||
for (rp = agg_route_top(ripng->table); rp;
|
||||
rp = agg_route_next(rp))
|
||||
@ -173,16 +176,15 @@ static int ripng_if_down(struct interface *ifp)
|
||||
for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
|
||||
rinfo))
|
||||
if (rinfo->ifindex == ifp->ifindex)
|
||||
ripng_ecmp_delete(rinfo);
|
||||
ripng_ecmp_delete(ripng, rinfo);
|
||||
|
||||
ri = ifp->info;
|
||||
|
||||
if (ri->running) {
|
||||
if (IS_RIPNG_DEBUG_EVENT)
|
||||
zlog_debug("turn off %s", ifp->name);
|
||||
|
||||
/* Leave from multicast group. */
|
||||
ripng_multicast_leave(ifp);
|
||||
ripng_multicast_leave(ifp, ripng->sock);
|
||||
|
||||
ri->running = 0;
|
||||
}
|
||||
@ -207,9 +209,11 @@ int ripng_interface_up(int command, struct zclient *zclient,
|
||||
|
||||
if (IS_RIPNG_DEBUG_ZEBRA)
|
||||
zlog_debug(
|
||||
"interface up %s index %d flags %llx metric %d mtu %d",
|
||||
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
|
||||
ifp->metric, ifp->mtu6);
|
||||
"interface up %s vrf %u index %d flags %llx metric %d mtu %d",
|
||||
ifp->name, ifp->vrf_id, ifp->ifindex,
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
|
||||
|
||||
ripng_interface_sync(ifp);
|
||||
|
||||
/* Check if this interface is RIPng enabled or not. */
|
||||
ripng_enable_apply(ifp);
|
||||
@ -238,13 +242,14 @@ int ripng_interface_down(int command, struct zclient *zclient,
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
ripng_interface_sync(ifp);
|
||||
ripng_if_down(ifp);
|
||||
|
||||
if (IS_RIPNG_DEBUG_ZEBRA)
|
||||
zlog_debug(
|
||||
"interface down %s index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
|
||||
ifp->metric, ifp->mtu6);
|
||||
"interface down %s vrf %u index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->vrf_id, ifp->ifindex,
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -256,12 +261,13 @@ int ripng_interface_add(int command, struct zclient *zclient,
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
|
||||
ripng_interface_sync(ifp);
|
||||
|
||||
if (IS_RIPNG_DEBUG_ZEBRA)
|
||||
zlog_debug(
|
||||
"RIPng interface add %s index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
|
||||
ifp->metric, ifp->mtu6);
|
||||
"RIPng interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->vrf_id, ifp->ifindex,
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
|
||||
|
||||
/* Check is this interface is RIP enabled or not.*/
|
||||
ripng_enable_apply(ifp);
|
||||
@ -289,13 +295,15 @@ int ripng_interface_delete(int command, struct zclient *zclient,
|
||||
if (ifp == NULL)
|
||||
return 0;
|
||||
|
||||
ripng_interface_sync(ifp);
|
||||
if (if_is_up(ifp)) {
|
||||
ripng_if_down(ifp);
|
||||
}
|
||||
|
||||
zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
|
||||
ifp->metric, ifp->mtu6);
|
||||
zlog_info(
|
||||
"interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
|
||||
ifp->name, ifp->vrf_id, ifp->ifindex,
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
|
||||
|
||||
/* To support pseudo interface do not free interface structure. */
|
||||
/* if_delete(ifp); */
|
||||
@ -304,13 +312,34 @@ int ripng_interface_delete(int command, struct zclient *zclient,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ripng_interface_clean(void)
|
||||
/* VRF update for an interface. */
|
||||
int ripng_interface_vrf_update(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct interface *ifp;
|
||||
vrf_id_t new_vrf_id;
|
||||
|
||||
ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
|
||||
&new_vrf_id);
|
||||
if (!ifp)
|
||||
return 0;
|
||||
|
||||
if (IS_RIPNG_DEBUG_ZEBRA)
|
||||
zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
|
||||
ifp->name, vrf_id, new_vrf_id);
|
||||
|
||||
if_update_to_new_vrf(ifp, new_vrf_id);
|
||||
ripng_interface_sync(ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ripng_interface_clean(struct ripng *ripng)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
struct ripng_interface *ri;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
FOR_ALL_INTERFACES (ripng->vrf, ifp) {
|
||||
ri = ifp->info;
|
||||
|
||||
ri->enable_network = 0;
|
||||
@ -326,6 +355,8 @@ void ripng_interface_clean(void)
|
||||
|
||||
static void ripng_apply_address_add(struct connected *ifc)
|
||||
{
|
||||
struct ripng_interface *ri = ifc->ifp->info;
|
||||
struct ripng *ripng = ri->ripng;
|
||||
struct prefix_ipv6 address;
|
||||
struct prefix *p;
|
||||
|
||||
@ -345,9 +376,9 @@ static void ripng_apply_address_add(struct connected *ifc)
|
||||
|
||||
/* Check if this interface is RIP enabled or not
|
||||
or Check if this address's prefix is RIP enabled */
|
||||
if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0)
|
||||
if ((ripng_enable_if_lookup(ripng, ifc->ifp->name) >= 0)
|
||||
|| (ripng_enable_network_lookup2(ifc) >= 0))
|
||||
ripng_redistribute_add(ZEBRA_ROUTE_CONNECT,
|
||||
ripng_redistribute_add(ripng, ZEBRA_ROUTE_CONNECT,
|
||||
RIPNG_ROUTE_INTERFACE, &address,
|
||||
ifc->ifp->ifindex, NULL, 0);
|
||||
}
|
||||
@ -395,6 +426,8 @@ int ripng_interface_address_add(int command, struct zclient *zclient,
|
||||
|
||||
static void ripng_apply_address_del(struct connected *ifc)
|
||||
{
|
||||
struct ripng_interface *ri = ifc->ifp->info;
|
||||
struct ripng *ripng = ri->ripng;
|
||||
struct prefix_ipv6 address;
|
||||
struct prefix *p;
|
||||
|
||||
@ -412,8 +445,9 @@ static void ripng_apply_address_del(struct connected *ifc)
|
||||
address.prefixlen = p->prefixlen;
|
||||
apply_mask_ipv6(&address);
|
||||
|
||||
ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
|
||||
&address, ifc->ifp->ifindex);
|
||||
ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT,
|
||||
RIPNG_ROUTE_INTERFACE, &address,
|
||||
ifc->ifp->ifindex);
|
||||
}
|
||||
|
||||
int ripng_interface_address_delete(int command, struct zclient *zclient,
|
||||
@ -446,21 +480,20 @@ int ripng_interface_address_delete(int command, struct zclient *zclient,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RIPng enable interface vector. */
|
||||
vector ripng_enable_if;
|
||||
|
||||
/* RIPng enable network table. */
|
||||
struct agg_table *ripng_enable_network;
|
||||
|
||||
/* Lookup RIPng enable network. */
|
||||
/* Check wether the interface has at least a connected prefix that
|
||||
* is within the ripng_enable_network table. */
|
||||
* is within the ripng->enable_network table. */
|
||||
static int ripng_enable_network_lookup_if(struct interface *ifp)
|
||||
{
|
||||
struct ripng_interface *ri = ifp->info;
|
||||
struct ripng *ripng = ri->ripng;
|
||||
struct listnode *node;
|
||||
struct connected *connected;
|
||||
struct prefix_ipv6 address;
|
||||
|
||||
if (!ripng)
|
||||
return -1;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
|
||||
struct prefix *p;
|
||||
struct agg_node *n;
|
||||
@ -472,7 +505,7 @@ static int ripng_enable_network_lookup_if(struct interface *ifp)
|
||||
address.prefix = p->u.prefix6;
|
||||
address.prefixlen = IPV6_MAX_BITLEN;
|
||||
|
||||
n = agg_node_match(ripng_enable_network,
|
||||
n = agg_node_match(ripng->enable_network,
|
||||
(struct prefix *)&address);
|
||||
if (n) {
|
||||
agg_unlock_node(n);
|
||||
@ -483,12 +516,17 @@ static int ripng_enable_network_lookup_if(struct interface *ifp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check wether connected is within the ripng_enable_network table. */
|
||||
/* Check wether connected is within the ripng->enable_network table. */
|
||||
static int ripng_enable_network_lookup2(struct connected *connected)
|
||||
{
|
||||
struct ripng_interface *ri = connected->ifp->info;
|
||||
struct ripng *ripng = ri->ripng;
|
||||
struct prefix_ipv6 address;
|
||||
struct prefix *p;
|
||||
|
||||
if (!ripng)
|
||||
return -1;
|
||||
|
||||
p = connected->address;
|
||||
|
||||
if (p->family == AF_INET6) {
|
||||
@ -499,8 +537,8 @@ static int ripng_enable_network_lookup2(struct connected *connected)
|
||||
address.prefixlen = IPV6_MAX_BITLEN;
|
||||
|
||||
/* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within
|
||||
* ripng_enable_network */
|
||||
node = agg_node_match(ripng_enable_network,
|
||||
* ripng->enable_network */
|
||||
node = agg_node_match(ripng->enable_network,
|
||||
(struct prefix *)&address);
|
||||
|
||||
if (node) {
|
||||
@ -513,11 +551,11 @@ static int ripng_enable_network_lookup2(struct connected *connected)
|
||||
}
|
||||
|
||||
/* Add RIPng enable network. */
|
||||
int ripng_enable_network_add(struct prefix *p)
|
||||
int ripng_enable_network_add(struct ripng *ripng, struct prefix *p)
|
||||
{
|
||||
struct agg_node *node;
|
||||
|
||||
node = agg_node_get(ripng_enable_network, p);
|
||||
node = agg_node_get(ripng->enable_network, p);
|
||||
|
||||
if (node->info) {
|
||||
agg_unlock_node(node);
|
||||
@ -526,17 +564,17 @@ int ripng_enable_network_add(struct prefix *p)
|
||||
node->info = (void *)1;
|
||||
|
||||
/* XXX: One should find a better solution than a generic one */
|
||||
ripng_enable_apply_all();
|
||||
ripng_enable_apply_all(ripng);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/* Delete RIPng enable network. */
|
||||
int ripng_enable_network_delete(struct prefix *p)
|
||||
int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p)
|
||||
{
|
||||
struct agg_node *node;
|
||||
|
||||
node = agg_node_lookup(ripng_enable_network, p);
|
||||
node = agg_node_lookup(ripng->enable_network, p);
|
||||
if (node) {
|
||||
node->info = NULL;
|
||||
|
||||
@ -553,49 +591,50 @@ int ripng_enable_network_delete(struct prefix *p)
|
||||
}
|
||||
|
||||
/* Lookup function. */
|
||||
static int ripng_enable_if_lookup(const char *ifname)
|
||||
static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname)
|
||||
{
|
||||
unsigned int i;
|
||||
char *str;
|
||||
|
||||
for (i = 0; i < vector_active(ripng_enable_if); i++)
|
||||
if ((str = vector_slot(ripng_enable_if, i)) != NULL)
|
||||
if (!ripng)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < vector_active(ripng->enable_if); i++)
|
||||
if ((str = vector_slot(ripng->enable_if, i)) != NULL)
|
||||
if (strcmp(str, ifname) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add interface to ripng_enable_if. */
|
||||
int ripng_enable_if_add(const char *ifname)
|
||||
int ripng_enable_if_add(struct ripng *ripng, const char *ifname)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ripng_enable_if_lookup(ifname);
|
||||
ret = ripng_enable_if_lookup(ripng, ifname);
|
||||
if (ret >= 0)
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
|
||||
vector_set(ripng_enable_if, strdup(ifname));
|
||||
vector_set(ripng->enable_if, strdup(ifname));
|
||||
|
||||
ripng_enable_apply_all();
|
||||
ripng_enable_apply_all(ripng);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/* Delete interface from ripng_enable_if. */
|
||||
int ripng_enable_if_delete(const char *ifname)
|
||||
int ripng_enable_if_delete(struct ripng *ripng, const char *ifname)
|
||||
{
|
||||
int index;
|
||||
char *str;
|
||||
|
||||
index = ripng_enable_if_lookup(ifname);
|
||||
index = ripng_enable_if_lookup(ripng, ifname);
|
||||
if (index < 0)
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
|
||||
str = vector_slot(ripng_enable_if, index);
|
||||
str = vector_slot(ripng->enable_if, index);
|
||||
free(str);
|
||||
vector_unset(ripng_enable_if, index);
|
||||
vector_unset(ripng->enable_if, index);
|
||||
|
||||
ripng_enable_apply_all();
|
||||
ripng_enable_apply_all(ripng);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -613,7 +652,7 @@ static int ripng_interface_wakeup(struct thread *t)
|
||||
ri->t_wakeup = NULL;
|
||||
|
||||
/* Join to multicast group. */
|
||||
if (ripng_multicast_join(ifp) < 0) {
|
||||
if (ripng_multicast_join(ifp, ri->ripng->sock) < 0) {
|
||||
flog_err_sys(EC_LIB_SOCKET,
|
||||
"multicast join failed, interface %s not running",
|
||||
ifp->name);
|
||||
@ -631,6 +670,8 @@ static int ripng_interface_wakeup(struct thread *t)
|
||||
|
||||
static void ripng_connect_set(struct interface *ifp, int set)
|
||||
{
|
||||
struct ripng_interface *ri = ifp->info;
|
||||
struct ripng *ripng = ri->ripng;
|
||||
struct listnode *node, *nnode;
|
||||
struct connected *connected;
|
||||
struct prefix_ipv6 address;
|
||||
@ -650,19 +691,22 @@ static void ripng_connect_set(struct interface *ifp, int set)
|
||||
if (set) {
|
||||
/* Check once more wether this prefix is within a
|
||||
* "network IF_OR_PREF" one */
|
||||
if ((ripng_enable_if_lookup(connected->ifp->name) >= 0)
|
||||
if ((ripng_enable_if_lookup(ripng, connected->ifp->name)
|
||||
>= 0)
|
||||
|| (ripng_enable_network_lookup2(connected) >= 0))
|
||||
ripng_redistribute_add(
|
||||
ZEBRA_ROUTE_CONNECT,
|
||||
ripng, ZEBRA_ROUTE_CONNECT,
|
||||
RIPNG_ROUTE_INTERFACE, &address,
|
||||
connected->ifp->ifindex, NULL, 0);
|
||||
} else {
|
||||
ripng_redistribute_delete(
|
||||
ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
|
||||
&address, connected->ifp->ifindex);
|
||||
if (ripng_redistribute_check(ZEBRA_ROUTE_CONNECT))
|
||||
ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT,
|
||||
RIPNG_ROUTE_INTERFACE,
|
||||
&address,
|
||||
connected->ifp->ifindex);
|
||||
if (ripng_redistribute_check(ripng,
|
||||
ZEBRA_ROUTE_CONNECT))
|
||||
ripng_redistribute_add(
|
||||
ZEBRA_ROUTE_CONNECT,
|
||||
ripng, ZEBRA_ROUTE_CONNECT,
|
||||
RIPNG_ROUTE_REDISTRIBUTE, &address,
|
||||
connected->ifp->ifindex, NULL, 0);
|
||||
}
|
||||
@ -691,7 +735,7 @@ void ripng_enable_apply(struct interface *ifp)
|
||||
ri->enable_network = 0;
|
||||
|
||||
/* Check interface name configuration. */
|
||||
ret = ripng_enable_if_lookup(ifp->name);
|
||||
ret = ripng_enable_if_lookup(ri->ripng, ifp->name);
|
||||
if (ret >= 0)
|
||||
ri->enable_interface = 1;
|
||||
else
|
||||
@ -729,49 +773,46 @@ void ripng_enable_apply(struct interface *ifp)
|
||||
}
|
||||
|
||||
/* Set distribute list to all interfaces. */
|
||||
static void ripng_enable_apply_all(void)
|
||||
static void ripng_enable_apply_all(struct ripng *ripng)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp)
|
||||
FOR_ALL_INTERFACES (ripng->vrf, ifp)
|
||||
ripng_enable_apply(ifp);
|
||||
}
|
||||
|
||||
/* Clear all network and neighbor configuration */
|
||||
void ripng_clean_network(void)
|
||||
void ripng_clean_network(struct ripng *ripng)
|
||||
{
|
||||
unsigned int i;
|
||||
char *str;
|
||||
struct agg_node *rn;
|
||||
|
||||
/* ripng_enable_network */
|
||||
for (rn = agg_route_top(ripng_enable_network); rn;
|
||||
/* ripng->enable_network */
|
||||
for (rn = agg_route_top(ripng->enable_network); rn;
|
||||
rn = agg_route_next(rn))
|
||||
if (rn->info) {
|
||||
rn->info = NULL;
|
||||
agg_unlock_node(rn);
|
||||
}
|
||||
|
||||
/* ripng_enable_if */
|
||||
for (i = 0; i < vector_active(ripng_enable_if); i++)
|
||||
if ((str = vector_slot(ripng_enable_if, i)) != NULL) {
|
||||
/* ripng->enable_if */
|
||||
for (i = 0; i < vector_active(ripng->enable_if); i++)
|
||||
if ((str = vector_slot(ripng->enable_if, i)) != NULL) {
|
||||
free(str);
|
||||
vector_slot(ripng_enable_if, i) = NULL;
|
||||
vector_slot(ripng->enable_if, i) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Vector to store passive-interface name. */
|
||||
vector Vripng_passive_interface;
|
||||
|
||||
/* Utility function for looking up passive interface settings. */
|
||||
static int ripng_passive_interface_lookup(const char *ifname)
|
||||
static int ripng_passive_interface_lookup(struct ripng *ripng,
|
||||
const char *ifname)
|
||||
{
|
||||
unsigned int i;
|
||||
char *str;
|
||||
|
||||
for (i = 0; i < vector_active(Vripng_passive_interface); i++)
|
||||
if ((str = vector_slot(Vripng_passive_interface, i)) != NULL)
|
||||
for (i = 0; i < vector_active(ripng->passive_interface); i++)
|
||||
if ((str = vector_slot(ripng->passive_interface, i)) != NULL)
|
||||
if (strcmp(str, ifname) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
@ -781,72 +822,75 @@ void ripng_passive_interface_apply(struct interface *ifp)
|
||||
{
|
||||
int ret;
|
||||
struct ripng_interface *ri;
|
||||
struct ripng *ripng;
|
||||
|
||||
ri = ifp->info;
|
||||
ripng = ri->ripng;
|
||||
if (!ripng)
|
||||
return;
|
||||
|
||||
ret = ripng_passive_interface_lookup(ifp->name);
|
||||
ret = ripng_passive_interface_lookup(ripng, ifp->name);
|
||||
if (ret < 0)
|
||||
ri->passive = 0;
|
||||
else
|
||||
ri->passive = 1;
|
||||
}
|
||||
|
||||
static void ripng_passive_interface_apply_all(void)
|
||||
static void ripng_passive_interface_apply_all(struct ripng *ripng)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp)
|
||||
FOR_ALL_INTERFACES (ripng->vrf, ifp)
|
||||
ripng_passive_interface_apply(ifp);
|
||||
}
|
||||
|
||||
/* Passive interface. */
|
||||
int ripng_passive_interface_set(const char *ifname)
|
||||
int ripng_passive_interface_set(struct ripng *ripng, const char *ifname)
|
||||
{
|
||||
if (ripng_passive_interface_lookup(ifname) >= 0)
|
||||
if (ripng_passive_interface_lookup(ripng, ifname) >= 0)
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
|
||||
vector_set(Vripng_passive_interface, strdup(ifname));
|
||||
vector_set(ripng->passive_interface, strdup(ifname));
|
||||
|
||||
ripng_passive_interface_apply_all();
|
||||
ripng_passive_interface_apply_all(ripng);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int ripng_passive_interface_unset(const char *ifname)
|
||||
int ripng_passive_interface_unset(struct ripng *ripng, const char *ifname)
|
||||
{
|
||||
int i;
|
||||
char *str;
|
||||
|
||||
i = ripng_passive_interface_lookup(ifname);
|
||||
i = ripng_passive_interface_lookup(ripng, ifname);
|
||||
if (i < 0)
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
|
||||
str = vector_slot(Vripng_passive_interface, i);
|
||||
str = vector_slot(ripng->passive_interface, i);
|
||||
free(str);
|
||||
vector_unset(Vripng_passive_interface, i);
|
||||
vector_unset(ripng->passive_interface, i);
|
||||
|
||||
ripng_passive_interface_apply_all();
|
||||
ripng_passive_interface_apply_all(ripng);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/* Free all configured RIP passive-interface settings. */
|
||||
void ripng_passive_interface_clean(void)
|
||||
void ripng_passive_interface_clean(struct ripng *ripng)
|
||||
{
|
||||
unsigned int i;
|
||||
char *str;
|
||||
|
||||
for (i = 0; i < vector_active(Vripng_passive_interface); i++)
|
||||
if ((str = vector_slot(Vripng_passive_interface, i)) != NULL) {
|
||||
for (i = 0; i < vector_active(ripng->passive_interface); i++)
|
||||
if ((str = vector_slot(ripng->passive_interface, i)) != NULL) {
|
||||
free(str);
|
||||
vector_slot(Vripng_passive_interface, i) = NULL;
|
||||
vector_slot(ripng->passive_interface, i) = NULL;
|
||||
}
|
||||
ripng_passive_interface_apply_all();
|
||||
ripng_passive_interface_apply_all(ripng);
|
||||
}
|
||||
|
||||
/* Write RIPng enable network and interface to the vty. */
|
||||
int ripng_network_write(struct vty *vty)
|
||||
int ripng_network_write(struct vty *vty, struct ripng *ripng)
|
||||
{
|
||||
unsigned int i;
|
||||
const char *ifname;
|
||||
@ -854,7 +898,7 @@ int ripng_network_write(struct vty *vty)
|
||||
char buf[BUFSIZ];
|
||||
|
||||
/* Write enable network. */
|
||||
for (node = agg_route_top(ripng_enable_network); node;
|
||||
for (node = agg_route_top(ripng->enable_network); node;
|
||||
node = agg_route_next(node))
|
||||
if (node->info) {
|
||||
struct prefix *p = &node->p;
|
||||
@ -864,8 +908,8 @@ int ripng_network_write(struct vty *vty)
|
||||
}
|
||||
|
||||
/* Write enable interface. */
|
||||
for (i = 0; i < vector_active(ripng_enable_if); i++)
|
||||
if ((ifname = vector_slot(ripng_enable_if, i)) != NULL)
|
||||
for (i = 0; i < vector_active(ripng->enable_if); i++)
|
||||
if ((ifname = vector_slot(ripng->enable_if, i)) != NULL)
|
||||
vty_out(vty, " %s\n", ifname);
|
||||
|
||||
return 0;
|
||||
@ -874,6 +918,7 @@ int ripng_network_write(struct vty *vty)
|
||||
static struct ripng_interface *ri_new(void)
|
||||
{
|
||||
struct ripng_interface *ri;
|
||||
|
||||
ri = XCALLOC(MTYPE_IF, sizeof(struct ripng_interface));
|
||||
|
||||
/* Set default split-horizon behavior. If the interface is Frame
|
||||
@ -886,9 +931,25 @@ static struct ripng_interface *ri_new(void)
|
||||
return ri;
|
||||
}
|
||||
|
||||
void ripng_interface_sync(struct interface *ifp)
|
||||
{
|
||||
struct vrf *vrf;
|
||||
|
||||
vrf = vrf_lookup_by_id(ifp->vrf_id);
|
||||
if (vrf) {
|
||||
struct ripng_interface *ri;
|
||||
|
||||
ri = ifp->info;
|
||||
if (ri)
|
||||
ri->ripng = vrf->info;
|
||||
}
|
||||
}
|
||||
|
||||
static int ripng_if_new_hook(struct interface *ifp)
|
||||
{
|
||||
ifp->info = ri_new();
|
||||
ripng_interface_sync(ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -903,10 +964,12 @@ static int ripng_if_delete_hook(struct interface *ifp)
|
||||
/* Configuration write function for ripngd. */
|
||||
static int interface_config_write(struct vty *vty)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
struct interface *ifp;
|
||||
struct vrf *vrf;
|
||||
int write = 0;
|
||||
|
||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||
struct interface *ifp;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
struct lyd_node *dnode;
|
||||
|
||||
@ -920,6 +983,7 @@ static int interface_config_write(struct vty *vty)
|
||||
write = 1;
|
||||
nb_cli_show_dnode_cmds(vty, dnode, false);
|
||||
}
|
||||
}
|
||||
|
||||
return write;
|
||||
}
|
||||
@ -936,15 +1000,6 @@ void ripng_if_init(void)
|
||||
hook_register_prio(if_add, 0, ripng_if_new_hook);
|
||||
hook_register_prio(if_del, 0, ripng_if_delete_hook);
|
||||
|
||||
/* RIPng enable network init. */
|
||||
ripng_enable_network = agg_table_init();
|
||||
|
||||
/* RIPng enable interface init. */
|
||||
ripng_enable_if = vector_init(1);
|
||||
|
||||
/* RIPng passive interface. */
|
||||
Vripng_passive_interface = vector_init(1);
|
||||
|
||||
/* Install interface node. */
|
||||
install_node(&interface_node, interface_config_write);
|
||||
if_cmd_init();
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "privs.h"
|
||||
#include "sigevent.h"
|
||||
#include "vrf.h"
|
||||
#include "if_rmap.h"
|
||||
#include "libfrr.h"
|
||||
|
||||
#include "ripngd/ripngd.h"
|
||||
@ -46,7 +47,7 @@
|
||||
struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}};
|
||||
|
||||
/* ripngd privileges */
|
||||
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
|
||||
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN};
|
||||
|
||||
struct zebra_privs_t ripngd_privs = {
|
||||
#if defined(FRR_USER)
|
||||
@ -59,7 +60,7 @@ struct zebra_privs_t ripngd_privs = {
|
||||
.vty_group = VTY_GROUP,
|
||||
#endif
|
||||
.caps_p = _caps_p,
|
||||
.cap_num_p = 2,
|
||||
.cap_num_p = array_size(_caps_p),
|
||||
.cap_num_i = 0};
|
||||
|
||||
|
||||
@ -82,8 +83,8 @@ static void sigint(void)
|
||||
{
|
||||
zlog_notice("Terminating on signal");
|
||||
|
||||
ripng_clean();
|
||||
|
||||
ripng_vrf_terminate();
|
||||
if_rmap_terminate();
|
||||
ripng_zebra_stop();
|
||||
frr_fini();
|
||||
exit(0);
|
||||
@ -170,13 +171,12 @@ int main(int argc, char **argv)
|
||||
master = frr_init();
|
||||
|
||||
/* Library inits. */
|
||||
vrf_init(NULL, NULL, NULL, NULL, NULL);
|
||||
ripng_vrf_init();
|
||||
|
||||
/* RIPngd inits. */
|
||||
ripng_init();
|
||||
ripng_cli_init();
|
||||
zebra_init(master);
|
||||
ripng_peer_init();
|
||||
|
||||
frr_config_fork();
|
||||
frr_run(master);
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
DEFINE_MGROUP(RIPNGD, "ripngd")
|
||||
DEFINE_MTYPE(RIPNGD, RIPNG, "RIPng structure")
|
||||
DEFINE_MTYPE(RIPNGD, RIPNG_VRF_NAME, "RIPng VRF name")
|
||||
DEFINE_MTYPE(RIPNGD, RIPNG_ROUTE, "RIPng route info")
|
||||
DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate")
|
||||
DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer")
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
DECLARE_MGROUP(RIPNGD)
|
||||
DECLARE_MTYPE(RIPNG)
|
||||
DECLARE_MTYPE(RIPNG_VRF_NAME)
|
||||
DECLARE_MTYPE(RIPNG_ROUTE)
|
||||
DECLARE_MTYPE(RIPNG_AGGREGATE)
|
||||
DECLARE_MTYPE(RIPNG_PEER)
|
||||
|
@ -114,7 +114,8 @@ void ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
|
||||
void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
|
||||
struct sockaddr_in6 *to)
|
||||
{
|
||||
|
||||
struct ripng_interface *ri = ifp->info;
|
||||
struct ripng *ripng = ri->ripng;
|
||||
struct ripng_rte_data *data;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "libfrr.h"
|
||||
|
||||
#include "ripngd/ripngd.h"
|
||||
#include "ripngd/ripng_debug.h"
|
||||
#include "ripngd/ripng_route.h"
|
||||
#include "ripngd/ripng_cli.h"
|
||||
|
||||
@ -42,41 +43,98 @@ static int ripngd_instance_create(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
struct vrf *vrf;
|
||||
const char *vrf_name;
|
||||
int socket;
|
||||
|
||||
vrf_name = yang_dnode_get_string(dnode, "./vrf");
|
||||
vrf = vrf_lookup_by_name(vrf_name);
|
||||
|
||||
/*
|
||||
* Try to create a RIPng socket only if the VRF is enabled, otherwise
|
||||
* create a disabled RIPng instance and wait for the VRF to be enabled.
|
||||
*/
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
break;
|
||||
case NB_EV_PREPARE:
|
||||
socket = ripng_make_socket();
|
||||
if (!vrf || !vrf_is_enabled(vrf))
|
||||
break;
|
||||
|
||||
socket = ripng_make_socket(vrf);
|
||||
if (socket < 0)
|
||||
return NB_ERR_RESOURCE;
|
||||
resource->fd = socket;
|
||||
break;
|
||||
case NB_EV_ABORT:
|
||||
if (!vrf || !vrf_is_enabled(vrf))
|
||||
break;
|
||||
|
||||
socket = resource->fd;
|
||||
close(socket);
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
if (vrf && vrf_is_enabled(vrf))
|
||||
socket = resource->fd;
|
||||
ripng_create(socket);
|
||||
else
|
||||
socket = -1;
|
||||
|
||||
ripng = ripng_create(vrf_name, vrf, socket);
|
||||
yang_dnode_set_entry(dnode, ripng);
|
||||
break;
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int ripngd_instance_delete(enum nb_event event,
|
||||
static int ripngd_instance_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng_clean();
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ripng_clean(ripng);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static const void *ripngd_instance_get_next(const void *parent_list_entry,
|
||||
const void *list_entry)
|
||||
{
|
||||
const struct ripng *ripng = list_entry;
|
||||
|
||||
if (list_entry == NULL)
|
||||
ripng = RB_MIN(ripng_instance_head, &ripng_instances);
|
||||
else
|
||||
ripng = RB_NEXT(ripng_instance_head, (struct ripng *)ripng);
|
||||
|
||||
return ripng;
|
||||
}
|
||||
|
||||
static int ripngd_instance_get_keys(const void *list_entry,
|
||||
struct yang_list_keys *keys)
|
||||
{
|
||||
const struct ripng *ripng = list_entry;
|
||||
|
||||
keys->num = 1;
|
||||
strlcpy(keys->key[0], ripng->vrf_name, sizeof(keys->key[0]));
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static const void *
|
||||
ripngd_instance_lookup_entry(const void *parent_list_entry,
|
||||
const struct yang_list_keys *keys)
|
||||
{
|
||||
const char *vrf_name = keys->key[0];
|
||||
|
||||
return ripng_lookup_by_vrf_name(vrf_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/instance/allow-ecmp
|
||||
*/
|
||||
@ -84,12 +142,15 @@ static int ripngd_instance_allow_ecmp_modify(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
|
||||
if (!ripng->ecmp)
|
||||
ripng_ecmp_disable();
|
||||
ripng_ecmp_disable(ripng);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -101,19 +162,22 @@ static int ripngd_instance_default_information_originate_modify(
|
||||
enum nb_event event, const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
bool default_information;
|
||||
struct prefix_ipv6 p;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
default_information = yang_dnode_get_bool(dnode, NULL);
|
||||
|
||||
str2prefix_ipv6("::/0", &p);
|
||||
if (default_information) {
|
||||
ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT,
|
||||
&p, 0, NULL, 0);
|
||||
ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
|
||||
RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
|
||||
} else {
|
||||
ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG,
|
||||
ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
|
||||
RIPNG_ROUTE_DEFAULT, &p, 0);
|
||||
}
|
||||
|
||||
@ -127,9 +191,12 @@ static int ripngd_instance_default_metric_modify(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
|
||||
|
||||
return NB_OK;
|
||||
@ -142,29 +209,33 @@ static int ripngd_instance_network_create(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
struct prefix p;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
yang_dnode_get_ipv6p(&p, dnode, NULL);
|
||||
apply_mask_ipv6((struct prefix_ipv6 *)&p);
|
||||
|
||||
return ripng_enable_network_add(&p);
|
||||
return ripng_enable_network_add(ripng, &p);
|
||||
}
|
||||
|
||||
static int ripngd_instance_network_delete(enum nb_event event,
|
||||
static int ripngd_instance_network_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
struct prefix p;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
yang_dnode_get_ipv6p(&p, dnode, NULL);
|
||||
apply_mask_ipv6((struct prefix_ipv6 *)&p);
|
||||
|
||||
return ripng_enable_network_delete(&p);
|
||||
return ripng_enable_network_delete(ripng, &p);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -174,27 +245,31 @@ static int ripngd_instance_interface_create(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
const char *ifname;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ifname = yang_dnode_get_string(dnode, NULL);
|
||||
|
||||
return ripng_enable_if_add(ifname);
|
||||
return ripng_enable_if_add(ripng, ifname);
|
||||
}
|
||||
|
||||
static int ripngd_instance_interface_delete(enum nb_event event,
|
||||
static int ripngd_instance_interface_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
const char *ifname;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ifname = yang_dnode_get_string(dnode, NULL);
|
||||
|
||||
return ripng_enable_if_delete(ifname);
|
||||
return ripng_enable_if_delete(ripng, ifname);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -204,21 +279,23 @@ static int ripngd_instance_offset_list_create(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
const char *ifname;
|
||||
struct ripng_offset_list *offset;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ifname = yang_dnode_get_string(dnode, "./interface");
|
||||
|
||||
offset = ripng_offset_list_new(ifname);
|
||||
offset = ripng_offset_list_new(ripng, ifname);
|
||||
yang_dnode_set_entry(dnode, offset);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int ripngd_instance_offset_list_delete(enum nb_event event,
|
||||
static int ripngd_instance_offset_list_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
int direct;
|
||||
@ -299,28 +376,32 @@ ripngd_instance_passive_interface_create(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
const char *ifname;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ifname = yang_dnode_get_string(dnode, NULL);
|
||||
|
||||
return ripng_passive_interface_set(ifname);
|
||||
return ripng_passive_interface_set(ripng, ifname);
|
||||
}
|
||||
|
||||
static int
|
||||
ripngd_instance_passive_interface_delete(enum nb_event event,
|
||||
ripngd_instance_passive_interface_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
const char *ifname;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ifname = yang_dnode_get_string(dnode, NULL);
|
||||
|
||||
return ripng_passive_interface_unset(ifname);
|
||||
return ripng_passive_interface_unset(ripng, ifname);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -330,20 +411,43 @@ static int ripngd_instance_redistribute_create(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int ripngd_instance_redistribute_delete(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
int type;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
type = yang_dnode_get_enum(dnode, "./protocol");
|
||||
|
||||
ripng_redistribute_conf_delete(type);
|
||||
ripng->redist[type].enabled = true;
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int ripngd_instance_redistribute_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
int type;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
type = yang_dnode_get_enum(dnode, "./protocol");
|
||||
|
||||
ripng->redist[type].enabled = false;
|
||||
if (ripng->redist[type].route_map.name) {
|
||||
free(ripng->redist[type].route_map.name);
|
||||
ripng->redist[type].route_map.name = NULL;
|
||||
ripng->redist[type].route_map.map = NULL;
|
||||
}
|
||||
ripng->redist[type].metric_config = false;
|
||||
ripng->redist[type].metric = 0;
|
||||
|
||||
if (ripng->enabled)
|
||||
ripng_redistribute_conf_delete(ripng, type);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -351,10 +455,14 @@ static int ripngd_instance_redistribute_delete(enum nb_event event,
|
||||
static void
|
||||
ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
int type;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
type = yang_dnode_get_enum(dnode, "./protocol");
|
||||
ripng_redistribute_conf_update(type);
|
||||
|
||||
if (ripng->enabled)
|
||||
ripng_redistribute_conf_update(ripng, type);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -365,37 +473,41 @@ ripngd_instance_redistribute_route_map_modify(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
int type;
|
||||
const char *rmap_name;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
type = yang_dnode_get_enum(dnode, "../protocol");
|
||||
rmap_name = yang_dnode_get_string(dnode, NULL);
|
||||
|
||||
if (ripng->route_map[type].name)
|
||||
free(ripng->route_map[type].name);
|
||||
ripng->route_map[type].name = strdup(rmap_name);
|
||||
ripng->route_map[type].map = route_map_lookup_by_name(rmap_name);
|
||||
if (ripng->redist[type].route_map.name)
|
||||
free(ripng->redist[type].route_map.name);
|
||||
ripng->redist[type].route_map.name = strdup(rmap_name);
|
||||
ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ripngd_instance_redistribute_route_map_delete(enum nb_event event,
|
||||
ripngd_instance_redistribute_route_map_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
int type;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
type = yang_dnode_get_enum(dnode, "../protocol");
|
||||
|
||||
free(ripng->route_map[type].name);
|
||||
ripng->route_map[type].name = NULL;
|
||||
ripng->route_map[type].map = NULL;
|
||||
free(ripng->redist[type].route_map.name);
|
||||
ripng->redist[type].route_map.name = NULL;
|
||||
ripng->redist[type].route_map.map = NULL;
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -408,34 +520,38 @@ ripngd_instance_redistribute_metric_modify(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
int type;
|
||||
uint8_t metric;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
type = yang_dnode_get_enum(dnode, "../protocol");
|
||||
metric = yang_dnode_get_uint8(dnode, NULL);
|
||||
|
||||
ripng->route_map[type].metric_config = true;
|
||||
ripng->route_map[type].metric = metric;
|
||||
ripng->redist[type].metric_config = true;
|
||||
ripng->redist[type].metric = metric;
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ripngd_instance_redistribute_metric_delete(enum nb_event event,
|
||||
ripngd_instance_redistribute_metric_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
int type;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
type = yang_dnode_get_enum(dnode, "../protocol");
|
||||
|
||||
ripng->route_map[type].metric_config = false;
|
||||
ripng->route_map[type].metric = 0;
|
||||
ripng->redist[type].metric_config = false;
|
||||
ripng->redist[type].metric = 0;
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -447,32 +563,37 @@ static int ripngd_instance_static_route_create(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
struct prefix_ipv6 p;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
yang_dnode_get_ipv6p(&p, dnode, NULL);
|
||||
apply_mask_ipv6(&p);
|
||||
|
||||
ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0,
|
||||
NULL, 0);
|
||||
ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
|
||||
0, NULL, 0);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int ripngd_instance_static_route_delete(enum nb_event event,
|
||||
static int ripngd_instance_static_route_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
struct prefix_ipv6 p;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
yang_dnode_get_ipv6p(&p, dnode, NULL);
|
||||
apply_mask_ipv6(&p);
|
||||
|
||||
ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
|
||||
ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
|
||||
&p, 0);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -485,32 +606,36 @@ ripngd_instance_aggregate_address_create(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
struct prefix_ipv6 p;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
yang_dnode_get_ipv6p(&p, dnode, NULL);
|
||||
apply_mask_ipv6(&p);
|
||||
|
||||
ripng_aggregate_add((struct prefix *)&p);
|
||||
ripng_aggregate_add(ripng, (struct prefix *)&p);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ripngd_instance_aggregate_address_delete(enum nb_event event,
|
||||
ripngd_instance_aggregate_address_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
struct prefix_ipv6 p;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
yang_dnode_get_ipv6p(&p, dnode, NULL);
|
||||
apply_mask_ipv6(&p);
|
||||
|
||||
ripng_aggregate_delete((struct prefix *)&p);
|
||||
ripng_aggregate_delete(ripng, (struct prefix *)&p);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -520,8 +645,12 @@ ripngd_instance_aggregate_address_delete(enum nb_event event,
|
||||
*/
|
||||
static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
|
||||
/* Reset update timer thread. */
|
||||
ripng_event(RIPNG_UPDATE_EVENT, 0);
|
||||
ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -532,9 +661,12 @@ ripngd_instance_timers_flush_interval_modify(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
|
||||
|
||||
return NB_OK;
|
||||
@ -548,9 +680,12 @@ ripngd_instance_timers_holddown_interval_modify(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
|
||||
|
||||
return NB_OK;
|
||||
@ -564,32 +699,37 @@ ripngd_instance_timers_update_interval_modify(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
|
||||
if (event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
ripng = yang_dnode_get_entry(dnode, true);
|
||||
ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor
|
||||
*/
|
||||
static const void *
|
||||
ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
|
||||
ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
|
||||
const void *list_entry)
|
||||
{
|
||||
const struct ripng *ripng = parent_list_entry;
|
||||
struct listnode *node;
|
||||
|
||||
if (list_entry == NULL)
|
||||
node = listhead(peer_list);
|
||||
node = listhead(ripng->peer_list);
|
||||
else
|
||||
node = listnextnode((struct listnode *)list_entry);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry,
|
||||
static int
|
||||
ripngd_instance_state_neighbors_neighbor_get_keys(const void *list_entry,
|
||||
struct yang_list_keys *keys)
|
||||
{
|
||||
const struct listnode *node = list_entry;
|
||||
@ -602,17 +742,17 @@ static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry,
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static const void *
|
||||
ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
|
||||
const struct yang_list_keys *keys)
|
||||
static const void *ripngd_instance_state_neighbors_neighbor_lookup_entry(
|
||||
const void *parent_list_entry, const struct yang_list_keys *keys)
|
||||
{
|
||||
const struct ripng *ripng = parent_list_entry;
|
||||
struct in6_addr address;
|
||||
struct ripng_peer *peer;
|
||||
struct listnode *node;
|
||||
|
||||
yang_str2ipv6(keys->key[0], &address);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(peer_list, node, peer)) {
|
||||
for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) {
|
||||
if (IPV6_ADDR_SAME(&peer->addr, &address))
|
||||
return node;
|
||||
}
|
||||
@ -621,11 +761,11 @@ ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/address
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/address
|
||||
*/
|
||||
static struct yang_data *
|
||||
ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath,
|
||||
const void *list_entry)
|
||||
ripngd_instance_state_neighbors_neighbor_address_get_elem(
|
||||
const char *xpath, const void *list_entry)
|
||||
{
|
||||
const struct listnode *node = list_entry;
|
||||
const struct ripng_peer *peer = listgetdata(node);
|
||||
@ -634,21 +774,21 @@ ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath,
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/last-update
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update
|
||||
*/
|
||||
static struct yang_data *
|
||||
ripngd_state_neighbors_neighbor_last_update_get_elem(const char *xpath,
|
||||
const void *list_entry)
|
||||
ripngd_instance_state_neighbors_neighbor_last_update_get_elem(
|
||||
const char *xpath, const void *list_entry)
|
||||
{
|
||||
/* TODO: yang:date-and-time is tricky */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd
|
||||
*/
|
||||
static struct yang_data *
|
||||
ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
|
||||
ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
|
||||
const char *xpath, const void *list_entry)
|
||||
{
|
||||
const struct listnode *node = list_entry;
|
||||
@ -658,11 +798,11 @@ ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd
|
||||
*/
|
||||
static struct yang_data *
|
||||
ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
|
||||
const void *list_entry)
|
||||
ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
|
||||
const char *xpath, const void *list_entry)
|
||||
{
|
||||
const struct listnode *node = list_entry;
|
||||
const struct ripng_peer *peer = listgetdata(node);
|
||||
@ -671,17 +811,15 @@ ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/routes/route
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/routes/route
|
||||
*/
|
||||
static const void *
|
||||
ripngd_state_routes_route_get_next(const void *parent_list_entry,
|
||||
ripngd_instance_state_routes_route_get_next(const void *parent_list_entry,
|
||||
const void *list_entry)
|
||||
{
|
||||
const struct ripng *ripng = parent_list_entry;
|
||||
struct agg_node *rn;
|
||||
|
||||
if (ripng == NULL)
|
||||
return NULL;
|
||||
|
||||
if (list_entry == NULL)
|
||||
rn = agg_route_top(ripng->table);
|
||||
else
|
||||
@ -692,7 +830,8 @@ ripngd_state_routes_route_get_next(const void *parent_list_entry,
|
||||
return rn;
|
||||
}
|
||||
|
||||
static int ripngd_state_routes_route_get_keys(const void *list_entry,
|
||||
static int
|
||||
ripngd_instance_state_routes_route_get_keys(const void *list_entry,
|
||||
struct yang_list_keys *keys)
|
||||
{
|
||||
const struct agg_node *rn = list_entry;
|
||||
@ -703,10 +842,10 @@ static int ripngd_state_routes_route_get_keys(const void *list_entry,
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static const void *
|
||||
ripngd_state_routes_route_lookup_entry(const void *parent_list_entry,
|
||||
const struct yang_list_keys *keys)
|
||||
static const void *ripngd_instance_state_routes_route_lookup_entry(
|
||||
const void *parent_list_entry, const struct yang_list_keys *keys)
|
||||
{
|
||||
const struct ripng *ripng = parent_list_entry;
|
||||
struct prefix prefix;
|
||||
struct agg_node *rn;
|
||||
|
||||
@ -722,10 +861,10 @@ ripngd_state_routes_route_lookup_entry(const void *parent_list_entry,
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/routes/route/prefix
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/routes/route/prefix
|
||||
*/
|
||||
static struct yang_data *
|
||||
ripngd_state_routes_route_prefix_get_elem(const char *xpath,
|
||||
ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath,
|
||||
const void *list_entry)
|
||||
{
|
||||
const struct agg_node *rn = list_entry;
|
||||
@ -735,10 +874,10 @@ ripngd_state_routes_route_prefix_get_elem(const char *xpath,
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/routes/route/next-hop
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/routes/route/next-hop
|
||||
*/
|
||||
static struct yang_data *
|
||||
ripngd_state_routes_route_next_hop_get_elem(const char *xpath,
|
||||
ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
|
||||
const void *list_entry)
|
||||
{
|
||||
const struct agg_node *rn = list_entry;
|
||||
@ -748,24 +887,25 @@ ripngd_state_routes_route_next_hop_get_elem(const char *xpath,
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/routes/route/interface
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/routes/route/interface
|
||||
*/
|
||||
static struct yang_data *
|
||||
ripngd_state_routes_route_interface_get_elem(const char *xpath,
|
||||
ripngd_instance_state_routes_route_interface_get_elem(const char *xpath,
|
||||
const void *list_entry)
|
||||
{
|
||||
const struct agg_node *rn = list_entry;
|
||||
const struct ripng_info *rinfo = listnode_head(rn->info);
|
||||
const struct ripng *ripng = ripng_info_get_instance(rinfo);
|
||||
|
||||
return yang_data_new_string(
|
||||
xpath, ifindex2ifname(rinfo->ifindex, VRF_DEFAULT));
|
||||
xpath, ifindex2ifname(rinfo->ifindex, ripng->vrf->vrf_id));
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-ripngd:ripngd/state/routes/route/metric
|
||||
* XPath: /frr-ripngd:ripngd/instance/state/routes/route/metric
|
||||
*/
|
||||
static struct yang_data *
|
||||
ripngd_state_routes_route_metric_get_elem(const char *xpath,
|
||||
ripngd_instance_state_routes_route_metric_get_elem(const char *xpath,
|
||||
const void *list_entry)
|
||||
{
|
||||
const struct agg_node *rn = list_entry;
|
||||
@ -777,16 +917,20 @@ ripngd_state_routes_route_metric_get_elem(const char *xpath,
|
||||
/*
|
||||
* XPath: /frr-ripngd:clear-ripng-route
|
||||
*/
|
||||
static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
|
||||
struct list *output)
|
||||
static void clear_ripng_route(struct ripng *ripng)
|
||||
{
|
||||
struct agg_node *rp;
|
||||
struct ripng_info *rinfo;
|
||||
struct list *list;
|
||||
struct listnode *listnode;
|
||||
|
||||
if (IS_RIPNG_DEBUG_EVENT)
|
||||
zlog_debug("Clearing all RIPng routes (VRF %s)",
|
||||
ripng->vrf_name);
|
||||
|
||||
/* Clear received RIPng routes */
|
||||
for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
|
||||
struct list *list;
|
||||
struct listnode *listnode;
|
||||
struct ripng_info *rinfo;
|
||||
|
||||
list = rp->info;
|
||||
if (list == NULL)
|
||||
continue;
|
||||
@ -796,7 +940,7 @@ static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
|
||||
continue;
|
||||
|
||||
if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
|
||||
ripng_zebra_ipv6_delete(rp);
|
||||
ripng_zebra_ipv6_delete(ripng, rp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -813,6 +957,30 @@ static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
|
||||
agg_unlock_node(rp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
|
||||
struct list *output)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
struct yang_data *yang_vrf;
|
||||
|
||||
yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf");
|
||||
if (yang_vrf) {
|
||||
ripng = ripng_lookup_by_vrf_name(yang_vrf->value);
|
||||
if (ripng)
|
||||
clear_ripng_route(ripng);
|
||||
} else {
|
||||
struct vrf *vrf;
|
||||
|
||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||
ripng = vrf->info;
|
||||
if (!ripng)
|
||||
continue;
|
||||
|
||||
clear_ripng_route(ripng);
|
||||
}
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
@ -845,7 +1013,10 @@ const struct frr_yang_module_info frr_ripngd_info = {
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance",
|
||||
.cbs.create = ripngd_instance_create,
|
||||
.cbs.destroy = ripngd_instance_delete,
|
||||
.cbs.destroy = ripngd_instance_destroy,
|
||||
.cbs.get_next = ripngd_instance_get_next,
|
||||
.cbs.get_keys = ripngd_instance_get_keys,
|
||||
.cbs.lookup_entry = ripngd_instance_lookup_entry,
|
||||
.cbs.cli_show = cli_show_router_ripng,
|
||||
},
|
||||
{
|
||||
@ -866,19 +1037,19 @@ const struct frr_yang_module_info frr_ripngd_info = {
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance/network",
|
||||
.cbs.create = ripngd_instance_network_create,
|
||||
.cbs.destroy = ripngd_instance_network_delete,
|
||||
.cbs.destroy = ripngd_instance_network_destroy,
|
||||
.cbs.cli_show = cli_show_ripng_network_prefix,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance/interface",
|
||||
.cbs.create = ripngd_instance_interface_create,
|
||||
.cbs.destroy = ripngd_instance_interface_delete,
|
||||
.cbs.destroy = ripngd_instance_interface_destroy,
|
||||
.cbs.cli_show = cli_show_ripng_network_interface,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance/offset-list",
|
||||
.cbs.create = ripngd_instance_offset_list_create,
|
||||
.cbs.destroy = ripngd_instance_offset_list_delete,
|
||||
.cbs.destroy = ripngd_instance_offset_list_destroy,
|
||||
.cbs.cli_show = cli_show_ripng_offset_list,
|
||||
},
|
||||
{
|
||||
@ -892,36 +1063,36 @@ const struct frr_yang_module_info frr_ripngd_info = {
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance/passive-interface",
|
||||
.cbs.create = ripngd_instance_passive_interface_create,
|
||||
.cbs.destroy = ripngd_instance_passive_interface_delete,
|
||||
.cbs.destroy = ripngd_instance_passive_interface_destroy,
|
||||
.cbs.cli_show = cli_show_ripng_passive_interface,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance/redistribute",
|
||||
.cbs.create = ripngd_instance_redistribute_create,
|
||||
.cbs.destroy = ripngd_instance_redistribute_delete,
|
||||
.cbs.destroy = ripngd_instance_redistribute_destroy,
|
||||
.cbs.apply_finish = ripngd_instance_redistribute_apply_finish,
|
||||
.cbs.cli_show = cli_show_ripng_redistribute,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
|
||||
.cbs.modify = ripngd_instance_redistribute_route_map_modify,
|
||||
.cbs.destroy = ripngd_instance_redistribute_route_map_delete,
|
||||
.cbs.destroy = ripngd_instance_redistribute_route_map_destroy,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
|
||||
.cbs.modify = ripngd_instance_redistribute_metric_modify,
|
||||
.cbs.destroy = ripngd_instance_redistribute_metric_delete,
|
||||
.cbs.destroy = ripngd_instance_redistribute_metric_destroy,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance/static-route",
|
||||
.cbs.create = ripngd_instance_static_route_create,
|
||||
.cbs.destroy = ripngd_instance_static_route_delete,
|
||||
.cbs.destroy = ripngd_instance_static_route_destroy,
|
||||
.cbs.cli_show = cli_show_ripng_route,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
|
||||
.cbs.create = ripngd_instance_aggregate_address_create,
|
||||
.cbs.destroy = ripngd_instance_aggregate_address_delete,
|
||||
.cbs.destroy = ripngd_instance_aggregate_address_destroy,
|
||||
.cbs.cli_show = cli_show_ripng_aggregate_address,
|
||||
},
|
||||
{
|
||||
@ -942,48 +1113,48 @@ const struct frr_yang_module_info frr_ripngd_info = {
|
||||
.cbs.modify = ripngd_instance_timers_update_interval_modify,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor",
|
||||
.cbs.get_next = ripngd_state_neighbors_neighbor_get_next,
|
||||
.cbs.get_keys = ripngd_state_neighbors_neighbor_get_keys,
|
||||
.cbs.lookup_entry = ripngd_state_neighbors_neighbor_lookup_entry,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor",
|
||||
.cbs.get_next = ripngd_instance_state_neighbors_neighbor_get_next,
|
||||
.cbs.get_keys = ripngd_instance_state_neighbors_neighbor_get_keys,
|
||||
.cbs.lookup_entry = ripngd_instance_state_neighbors_neighbor_lookup_entry,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/address",
|
||||
.cbs.get_elem = ripngd_state_neighbors_neighbor_address_get_elem,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address",
|
||||
.cbs.get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/last-update",
|
||||
.cbs.get_elem = ripngd_state_neighbors_neighbor_last_update_get_elem,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update",
|
||||
.cbs.get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd",
|
||||
.cbs.get_elem = ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd",
|
||||
.cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd",
|
||||
.cbs.get_elem = ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd",
|
||||
.cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/routes/route",
|
||||
.cbs.get_next = ripngd_state_routes_route_get_next,
|
||||
.cbs.get_keys = ripngd_state_routes_route_get_keys,
|
||||
.cbs.lookup_entry = ripngd_state_routes_route_lookup_entry,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/routes/route",
|
||||
.cbs.get_next = ripngd_instance_state_routes_route_get_next,
|
||||
.cbs.get_keys = ripngd_instance_state_routes_route_get_keys,
|
||||
.cbs.lookup_entry = ripngd_instance_state_routes_route_lookup_entry,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/routes/route/prefix",
|
||||
.cbs.get_elem = ripngd_state_routes_route_prefix_get_elem,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix",
|
||||
.cbs.get_elem = ripngd_instance_state_routes_route_prefix_get_elem,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/routes/route/next-hop",
|
||||
.cbs.get_elem = ripngd_state_routes_route_next_hop_get_elem,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop",
|
||||
.cbs.get_elem = ripngd_instance_state_routes_route_next_hop_get_elem,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/routes/route/interface",
|
||||
.cbs.get_elem = ripngd_state_routes_route_interface_get_elem,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface",
|
||||
.cbs.get_elem = ripngd_instance_state_routes_route_interface_get_elem,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:ripngd/state/routes/route/metric",
|
||||
.cbs.get_elem = ripngd_state_routes_route_metric_get_elem,
|
||||
.xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric",
|
||||
.cbs.get_elem = ripngd_instance_state_routes_route_metric_get_elem,
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-ripngd:clear-ripng-route",
|
||||
|
@ -33,29 +33,29 @@
|
||||
|
||||
#include "ripngd/ripngd.h"
|
||||
|
||||
static struct list *ripng_offset_list_master;
|
||||
|
||||
#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
|
||||
#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
|
||||
|
||||
#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
|
||||
#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
|
||||
|
||||
struct ripng_offset_list *ripng_offset_list_new(const char *ifname)
|
||||
struct ripng_offset_list *ripng_offset_list_new(struct ripng *ripng,
|
||||
const char *ifname)
|
||||
{
|
||||
struct ripng_offset_list *new;
|
||||
|
||||
new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST,
|
||||
sizeof(struct ripng_offset_list));
|
||||
new->ripng = ripng;
|
||||
new->ifname = strdup(ifname);
|
||||
listnode_add_sort(ripng_offset_list_master, new);
|
||||
listnode_add_sort(ripng->offset_list_master, new);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
void ripng_offset_list_del(struct ripng_offset_list *offset)
|
||||
{
|
||||
listnode_delete(ripng_offset_list_master, offset);
|
||||
listnode_delete(offset->ripng->offset_list_master, offset);
|
||||
if (OFFSET_LIST_IN_NAME(offset))
|
||||
free(OFFSET_LIST_IN_NAME(offset));
|
||||
if (OFFSET_LIST_OUT_NAME(offset))
|
||||
@ -64,12 +64,14 @@ void ripng_offset_list_del(struct ripng_offset_list *offset)
|
||||
XFREE(MTYPE_RIPNG_OFFSET_LIST, offset);
|
||||
}
|
||||
|
||||
struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
|
||||
struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng,
|
||||
const char *ifname)
|
||||
{
|
||||
struct ripng_offset_list *offset;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) {
|
||||
for (ALL_LIST_ELEMENTS(ripng->offset_list_master, node, nnode,
|
||||
offset)) {
|
||||
if (strcmp(offset->ifname, ifname) == 0)
|
||||
return offset;
|
||||
}
|
||||
@ -77,14 +79,14 @@ struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
|
||||
}
|
||||
|
||||
/* If metric is modifed return 1. */
|
||||
int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
|
||||
uint8_t *metric)
|
||||
int ripng_offset_list_apply_in(struct ripng *ripng, struct prefix_ipv6 *p,
|
||||
struct interface *ifp, uint8_t *metric)
|
||||
{
|
||||
struct ripng_offset_list *offset;
|
||||
struct access_list *alist;
|
||||
|
||||
/* Look up offset-list with interface name. */
|
||||
offset = ripng_offset_list_lookup(ifp->name);
|
||||
offset = ripng_offset_list_lookup(ripng, ifp->name);
|
||||
if (offset && OFFSET_LIST_IN_NAME(offset)) {
|
||||
alist = access_list_lookup(AFI_IP6,
|
||||
OFFSET_LIST_IN_NAME(offset));
|
||||
@ -98,7 +100,7 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
|
||||
return 0;
|
||||
}
|
||||
/* Look up offset-list without interface name. */
|
||||
offset = ripng_offset_list_lookup("*");
|
||||
offset = ripng_offset_list_lookup(ripng, "*");
|
||||
if (offset && OFFSET_LIST_IN_NAME(offset)) {
|
||||
alist = access_list_lookup(AFI_IP6,
|
||||
OFFSET_LIST_IN_NAME(offset));
|
||||
@ -115,14 +117,14 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
|
||||
}
|
||||
|
||||
/* If metric is modifed return 1. */
|
||||
int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
|
||||
uint8_t *metric)
|
||||
int ripng_offset_list_apply_out(struct ripng *ripng, struct prefix_ipv6 *p,
|
||||
struct interface *ifp, uint8_t *metric)
|
||||
{
|
||||
struct ripng_offset_list *offset;
|
||||
struct access_list *alist;
|
||||
|
||||
/* Look up offset-list with interface name. */
|
||||
offset = ripng_offset_list_lookup(ifp->name);
|
||||
offset = ripng_offset_list_lookup(ripng, ifp->name);
|
||||
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
|
||||
alist = access_list_lookup(AFI_IP6,
|
||||
OFFSET_LIST_OUT_NAME(offset));
|
||||
@ -137,7 +139,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
|
||||
}
|
||||
|
||||
/* Look up offset-list without interface name. */
|
||||
offset = ripng_offset_list_lookup("*");
|
||||
offset = ripng_offset_list_lookup(ripng, "*");
|
||||
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
|
||||
alist = access_list_lookup(AFI_IP6,
|
||||
OFFSET_LIST_OUT_NAME(offset));
|
||||
@ -153,26 +155,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int offset_list_cmp(struct ripng_offset_list *o1,
|
||||
struct ripng_offset_list *o2)
|
||||
int offset_list_cmp(struct ripng_offset_list *o1, struct ripng_offset_list *o2)
|
||||
{
|
||||
return strcmp(o1->ifname, o2->ifname);
|
||||
}
|
||||
|
||||
void ripng_offset_init(void)
|
||||
{
|
||||
ripng_offset_list_master = list_new();
|
||||
ripng_offset_list_master->cmp =
|
||||
(int (*)(void *, void *))offset_list_cmp;
|
||||
ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
|
||||
}
|
||||
|
||||
void ripng_offset_clean(void)
|
||||
{
|
||||
list_delete(&ripng_offset_list_master);
|
||||
|
||||
ripng_offset_list_master = list_new();
|
||||
ripng_offset_list_master->cmp =
|
||||
(int (*)(void *, void *))offset_list_cmp;
|
||||
ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
|
||||
}
|
||||
|
@ -34,10 +34,6 @@
|
||||
#include "ripngd/ripngd.h"
|
||||
#include "ripngd/ripng_nexthop.h"
|
||||
|
||||
|
||||
/* Linked list of RIPng peer. */
|
||||
struct list *peer_list;
|
||||
|
||||
static struct ripng_peer *ripng_peer_new(void)
|
||||
{
|
||||
return XCALLOC(MTYPE_RIPNG_PEER, sizeof(struct ripng_peer));
|
||||
@ -45,27 +41,29 @@ static struct ripng_peer *ripng_peer_new(void)
|
||||
|
||||
static void ripng_peer_free(struct ripng_peer *peer)
|
||||
{
|
||||
RIPNG_TIMER_OFF(peer->t_timeout);
|
||||
XFREE(MTYPE_RIPNG_PEER, peer);
|
||||
}
|
||||
|
||||
struct ripng_peer *ripng_peer_lookup(struct in6_addr *addr)
|
||||
struct ripng_peer *ripng_peer_lookup(struct ripng *ripng, struct in6_addr *addr)
|
||||
{
|
||||
struct ripng_peer *peer;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
|
||||
for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
|
||||
if (IPV6_ADDR_SAME(&peer->addr, addr))
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *addr)
|
||||
struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng,
|
||||
struct in6_addr *addr)
|
||||
{
|
||||
struct ripng_peer *peer;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
|
||||
for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
|
||||
if (addr6_cmp(&peer->addr, addr) > 0)
|
||||
return peer;
|
||||
}
|
||||
@ -80,26 +78,28 @@ static int ripng_peer_timeout(struct thread *t)
|
||||
struct ripng_peer *peer;
|
||||
|
||||
peer = THREAD_ARG(t);
|
||||
listnode_delete(peer_list, peer);
|
||||
listnode_delete(peer->ripng->peer_list, peer);
|
||||
ripng_peer_free(peer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get RIPng peer. At the same time update timeout thread. */
|
||||
static struct ripng_peer *ripng_peer_get(struct in6_addr *addr)
|
||||
static struct ripng_peer *ripng_peer_get(struct ripng *ripng,
|
||||
struct in6_addr *addr)
|
||||
{
|
||||
struct ripng_peer *peer;
|
||||
|
||||
peer = ripng_peer_lookup(addr);
|
||||
peer = ripng_peer_lookup(ripng, addr);
|
||||
|
||||
if (peer) {
|
||||
if (peer->t_timeout)
|
||||
thread_cancel(peer->t_timeout);
|
||||
} else {
|
||||
peer = ripng_peer_new();
|
||||
peer->addr = *addr; /* XXX */
|
||||
listnode_add_sort(peer_list, peer);
|
||||
peer->ripng = ripng;
|
||||
peer->addr = *addr;
|
||||
listnode_add_sort(ripng->peer_list, peer);
|
||||
}
|
||||
|
||||
/* Update timeout thread. */
|
||||
@ -113,24 +113,25 @@ static struct ripng_peer *ripng_peer_get(struct in6_addr *addr)
|
||||
return peer;
|
||||
}
|
||||
|
||||
void ripng_peer_update(struct sockaddr_in6 *from, uint8_t version)
|
||||
void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from,
|
||||
uint8_t version)
|
||||
{
|
||||
struct ripng_peer *peer;
|
||||
peer = ripng_peer_get(&from->sin6_addr);
|
||||
peer = ripng_peer_get(ripng, &from->sin6_addr);
|
||||
peer->version = version;
|
||||
}
|
||||
|
||||
void ripng_peer_bad_route(struct sockaddr_in6 *from)
|
||||
void ripng_peer_bad_route(struct ripng *ripng, struct sockaddr_in6 *from)
|
||||
{
|
||||
struct ripng_peer *peer;
|
||||
peer = ripng_peer_get(&from->sin6_addr);
|
||||
peer = ripng_peer_get(ripng, &from->sin6_addr);
|
||||
peer->recv_badroutes++;
|
||||
}
|
||||
|
||||
void ripng_peer_bad_packet(struct sockaddr_in6 *from)
|
||||
void ripng_peer_bad_packet(struct ripng *ripng, struct sockaddr_in6 *from)
|
||||
{
|
||||
struct ripng_peer *peer;
|
||||
peer = ripng_peer_get(&from->sin6_addr);
|
||||
peer = ripng_peer_get(ripng, &from->sin6_addr);
|
||||
peer->recv_badpackets++;
|
||||
}
|
||||
|
||||
@ -163,14 +164,14 @@ static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len)
|
||||
return buf;
|
||||
}
|
||||
|
||||
void ripng_peer_display(struct vty *vty)
|
||||
void ripng_peer_display(struct vty *vty, struct ripng *ripng)
|
||||
{
|
||||
struct ripng_peer *peer;
|
||||
struct listnode *node, *nnode;
|
||||
#define RIPNG_UPTIME_LEN 25
|
||||
char timebuf[RIPNG_UPTIME_LEN];
|
||||
|
||||
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
|
||||
for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
|
||||
vty_out(vty, " %s \n%14s %10d %10d %10d %s\n",
|
||||
inet6_ntoa(peer->addr), " ", peer->recv_badpackets,
|
||||
peer->recv_badroutes, ZEBRA_RIPNG_DISTANCE_DEFAULT,
|
||||
@ -178,13 +179,12 @@ void ripng_peer_display(struct vty *vty)
|
||||
}
|
||||
}
|
||||
|
||||
static int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2)
|
||||
int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2)
|
||||
{
|
||||
return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
void ripng_peer_init(void)
|
||||
void ripng_peer_list_del(void *arg)
|
||||
{
|
||||
peer_list = list_new();
|
||||
peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp;
|
||||
ripng_peer_free(arg);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ void ripng_aggregate_decrement_list(struct agg_node *child, struct list *list)
|
||||
}
|
||||
|
||||
/* RIPng routes treatment. */
|
||||
int ripng_aggregate_add(struct prefix *p)
|
||||
int ripng_aggregate_add(struct ripng *ripng, struct prefix *p)
|
||||
{
|
||||
struct agg_node *top;
|
||||
struct agg_node *rp;
|
||||
@ -124,7 +124,7 @@ int ripng_aggregate_add(struct prefix *p)
|
||||
}
|
||||
|
||||
/* Delete RIPng static route. */
|
||||
int ripng_aggregate_delete(struct prefix *p)
|
||||
int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p)
|
||||
{
|
||||
struct agg_node *top;
|
||||
struct agg_node *rp;
|
||||
|
@ -48,8 +48,8 @@ extern void ripng_aggregate_decrement(struct agg_node *rp,
|
||||
struct ripng_info *rinfo);
|
||||
extern void ripng_aggregate_decrement_list(struct agg_node *rp,
|
||||
struct list *list);
|
||||
extern int ripng_aggregate_add(struct prefix *p);
|
||||
extern int ripng_aggregate_delete(struct prefix *p);
|
||||
extern int ripng_aggregate_add(struct ripng *ripng, struct prefix *p);
|
||||
extern int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p);
|
||||
extern void ripng_aggregate_free(struct ripng_aggregate *aggregate);
|
||||
|
||||
#endif /* _ZEBRA_RIPNG_ROUTE_H */
|
||||
|
@ -37,7 +37,8 @@
|
||||
struct zclient *zclient = NULL;
|
||||
|
||||
/* Send ECMP routes to zebra. */
|
||||
static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
|
||||
static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp,
|
||||
uint8_t cmd)
|
||||
{
|
||||
struct list *list = (struct list *)rp->info;
|
||||
struct zapi_route api;
|
||||
@ -47,7 +48,7 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
|
||||
int count = 0;
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.vrf_id = ripng->vrf->vrf_id;
|
||||
api.type = ZEBRA_ROUTE_RIPNG;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = rp->p;
|
||||
@ -57,7 +58,7 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
|
||||
if (count >= MULTIPATH_NUM)
|
||||
break;
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
api_nh->vrf_id = ripng->vrf->vrf_id;
|
||||
api_nh->gate.ipv6 = rinfo->nexthop;
|
||||
api_nh->ifindex = rinfo->ifindex;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
@ -100,25 +101,30 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
|
||||
}
|
||||
|
||||
/* Add/update ECMP routes to zebra. */
|
||||
void ripng_zebra_ipv6_add(struct agg_node *rp)
|
||||
void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *rp)
|
||||
{
|
||||
ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD);
|
||||
ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_ADD);
|
||||
}
|
||||
|
||||
/* Delete ECMP routes from zebra. */
|
||||
void ripng_zebra_ipv6_delete(struct agg_node *rp)
|
||||
void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *rp)
|
||||
{
|
||||
ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE);
|
||||
ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_DELETE);
|
||||
}
|
||||
|
||||
/* Zebra route add and delete treatment. */
|
||||
static int ripng_zebra_read_route(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct ripng *ripng;
|
||||
struct zapi_route api;
|
||||
struct in6_addr nexthop;
|
||||
unsigned long ifindex;
|
||||
|
||||
ripng = ripng_lookup_by_vrf_id(vrf_id);
|
||||
if (!ripng)
|
||||
return 0;
|
||||
|
||||
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
||||
return -1;
|
||||
|
||||
@ -133,69 +139,97 @@ static int ripng_zebra_read_route(int command, struct zclient *zclient,
|
||||
ifindex = api.nexthops[0].ifindex;
|
||||
|
||||
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
|
||||
ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
|
||||
ripng_redistribute_add(ripng, api.type,
|
||||
RIPNG_ROUTE_REDISTRIBUTE,
|
||||
(struct prefix_ipv6 *)&api.prefix,
|
||||
ifindex, &nexthop, api.tag);
|
||||
else
|
||||
ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
|
||||
(struct prefix_ipv6 *)&api.prefix,
|
||||
ifindex);
|
||||
ripng_redistribute_delete(
|
||||
ripng, api.type, RIPNG_ROUTE_REDISTRIBUTE,
|
||||
(struct prefix_ipv6 *)&api.prefix, ifindex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ripng_redistribute_conf_update(int type)
|
||||
void ripng_redistribute_conf_update(struct ripng *ripng, int type)
|
||||
{
|
||||
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
|
||||
VRF_DEFAULT);
|
||||
ripng->vrf->vrf_id);
|
||||
}
|
||||
|
||||
void ripng_redistribute_conf_delete(int type)
|
||||
void ripng_redistribute_conf_delete(struct ripng *ripng, int type)
|
||||
{
|
||||
if (zclient->sock > 0)
|
||||
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
|
||||
AFI_IP6, type, 0, VRF_DEFAULT);
|
||||
AFI_IP6, type, 0, ripng->vrf->vrf_id);
|
||||
|
||||
ripng_redistribute_withdraw(type);
|
||||
ripng_redistribute_withdraw(ripng, type);
|
||||
}
|
||||
|
||||
int ripng_redistribute_check(int type)
|
||||
int ripng_redistribute_check(struct ripng *ripng, int type)
|
||||
{
|
||||
return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
|
||||
return ripng->redist[type].enabled;
|
||||
}
|
||||
|
||||
void ripng_redistribute_clean(void)
|
||||
void ripng_redistribute_enable(struct ripng *ripng)
|
||||
{
|
||||
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT))
|
||||
if (!ripng_redistribute_check(ripng, i))
|
||||
continue;
|
||||
|
||||
if (zclient->sock > 0)
|
||||
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
|
||||
zclient, AFI_IP6, i, 0,
|
||||
VRF_DEFAULT);
|
||||
|
||||
vrf_bitmap_unset(zclient->redist[AFI_IP6][i], VRF_DEFAULT);
|
||||
|
||||
/* Remove the routes from RIP table. */
|
||||
ripng_redistribute_withdraw(i);
|
||||
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient,
|
||||
AFI_IP6, i, 0, ripng->vrf->vrf_id);
|
||||
}
|
||||
}
|
||||
|
||||
void ripng_redistribute_write(struct vty *vty)
|
||||
void ripng_redistribute_disable(struct ripng *ripng)
|
||||
{
|
||||
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (!ripng_redistribute_check(ripng, i))
|
||||
continue;
|
||||
|
||||
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
|
||||
AFI_IP6, i, 0, ripng->vrf->vrf_id);
|
||||
}
|
||||
}
|
||||
|
||||
void ripng_redistribute_write(struct vty *vty, struct ripng *ripng)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (i == zclient->redist_default
|
||||
|| !vrf_bitmap_check(zclient->redist[AFI_IP6][i],
|
||||
VRF_DEFAULT))
|
||||
|| !ripng_redistribute_check(ripng, i))
|
||||
continue;
|
||||
|
||||
vty_out(vty, " %s", zebra_route_string(i));
|
||||
}
|
||||
}
|
||||
|
||||
void ripng_zebra_vrf_register(struct vrf *vrf)
|
||||
{
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
return;
|
||||
|
||||
if (IS_RIPNG_DEBUG_EVENT)
|
||||
zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
|
||||
vrf->name, vrf->vrf_id);
|
||||
|
||||
zclient_send_reg_requests(zclient, vrf->vrf_id);
|
||||
}
|
||||
|
||||
void ripng_zebra_vrf_deregister(struct vrf *vrf)
|
||||
{
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
return;
|
||||
|
||||
if (IS_RIPNG_DEBUG_EVENT)
|
||||
zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
|
||||
vrf->name, vrf->vrf_id);
|
||||
|
||||
zclient_send_dereg_requests(zclient, vrf->vrf_id);
|
||||
}
|
||||
|
||||
static void ripng_zebra_connected(struct zclient *zclient)
|
||||
{
|
||||
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
||||
@ -215,6 +249,7 @@ void zebra_init(struct thread_master *master)
|
||||
zclient->interface_delete = ripng_interface_delete;
|
||||
zclient->interface_address_add = ripng_interface_address_add;
|
||||
zclient->interface_address_delete = ripng_interface_address_delete;
|
||||
zclient->interface_vrf_update = ripng_interface_vrf_update;
|
||||
zclient->redistribute_route_add = ripng_zebra_read_route;
|
||||
zclient->redistribute_route_del = ripng_zebra_read_route;
|
||||
}
|
||||
|
707
ripngd/ripngd.c
707
ripngd/ripngd.c
File diff suppressed because it is too large
Load Diff
168
ripngd/ripngd.h
168
ripngd/ripngd.h
@ -25,6 +25,7 @@
|
||||
#include <zclient.h>
|
||||
#include <vty.h>
|
||||
#include <distribute.h>
|
||||
#include <vector.h>
|
||||
|
||||
#include "ripng_memory.h"
|
||||
|
||||
@ -88,6 +89,17 @@
|
||||
|
||||
/* RIPng structure. */
|
||||
struct ripng {
|
||||
RB_ENTRY(ripng) entry;
|
||||
|
||||
/* VRF this routing instance is associated with. */
|
||||
char *vrf_name;
|
||||
|
||||
/* VRF backpointer (might be NULL if the VRF doesn't exist). */
|
||||
struct vrf *vrf;
|
||||
|
||||
/* Status of the routing instance. */
|
||||
bool enabled;
|
||||
|
||||
/* RIPng socket. */
|
||||
int sock;
|
||||
|
||||
@ -107,6 +119,21 @@ struct ripng {
|
||||
/* RIPng routing information base. */
|
||||
struct agg_table *table;
|
||||
|
||||
/* Linked list of RIPng peers. */
|
||||
struct list *peer_list;
|
||||
|
||||
/* RIPng enabled interfaces. */
|
||||
vector enable_if;
|
||||
|
||||
/* RIPng enabled networks. */
|
||||
struct agg_table *enable_network;
|
||||
|
||||
/* Vector to store passive-interface name. */
|
||||
vector passive_interface;
|
||||
|
||||
/* RIPng offset-lists. */
|
||||
struct list *offset_list_master;
|
||||
|
||||
/* RIPng threads. */
|
||||
struct thread *t_read;
|
||||
struct thread *t_write;
|
||||
@ -122,13 +149,16 @@ struct ripng {
|
||||
/* RIPng ECMP flag */
|
||||
bool ecmp;
|
||||
|
||||
/* For redistribute route map. */
|
||||
/* RIPng redistribute configuration. */
|
||||
struct {
|
||||
bool enabled;
|
||||
struct {
|
||||
char *name;
|
||||
struct route_map *map;
|
||||
} route_map;
|
||||
bool metric_config;
|
||||
uint8_t metric;
|
||||
} route_map[ZEBRA_ROUTE_MAX];
|
||||
} redist[ZEBRA_ROUTE_MAX];
|
||||
|
||||
/* For distribute-list container */
|
||||
struct distribute_ctx *distribute_ctx;
|
||||
@ -136,6 +166,8 @@ struct ripng {
|
||||
/* For if_rmap container */
|
||||
struct if_rmap_ctx *if_rmap_ctx;
|
||||
};
|
||||
RB_HEAD(ripng_instance_head, ripng);
|
||||
RB_PROTOTYPE(ripng_instance_head, ripng, entry, ripng_instance_compare)
|
||||
|
||||
/* Routing table entry. */
|
||||
struct rte {
|
||||
@ -234,6 +266,9 @@ typedef enum {
|
||||
|
||||
/* RIPng specific interface configuration. */
|
||||
struct ripng_interface {
|
||||
/* Parent routing instance. */
|
||||
struct ripng *ripng;
|
||||
|
||||
/* RIPng is enabled on this interface. */
|
||||
int enable_network;
|
||||
int enable_interface;
|
||||
@ -280,6 +315,9 @@ struct ripng_interface {
|
||||
|
||||
/* RIPng peer information. */
|
||||
struct ripng_peer {
|
||||
/* Parent routing instance. */
|
||||
struct ripng *ripng;
|
||||
|
||||
/* Peer address. */
|
||||
struct in6_addr addr;
|
||||
|
||||
@ -325,6 +363,9 @@ enum ripng_event {
|
||||
#define RIPNG_OFFSET_LIST_MAX 2
|
||||
|
||||
struct ripng_offset_list {
|
||||
/* Parent routing instance. */
|
||||
struct ripng *ripng;
|
||||
|
||||
char *ifname;
|
||||
|
||||
struct {
|
||||
@ -335,72 +376,87 @@ struct ripng_offset_list {
|
||||
};
|
||||
|
||||
/* Extern variables. */
|
||||
extern struct ripng *ripng;
|
||||
extern struct list *peer_list;
|
||||
extern struct zebra_privs_t ripngd_privs;
|
||||
extern struct thread_master *master;
|
||||
extern struct ripng_instance_head ripng_instances;
|
||||
|
||||
/* Prototypes. */
|
||||
extern void ripng_init(void);
|
||||
extern void ripng_clean(void);
|
||||
extern void ripng_clean_network(void);
|
||||
extern void ripng_interface_clean(void);
|
||||
extern int ripng_enable_network_add(struct prefix *p);
|
||||
extern int ripng_enable_network_delete(struct prefix *p);
|
||||
extern int ripng_enable_if_add(const char *ifname);
|
||||
extern int ripng_enable_if_delete(const char *ifname);
|
||||
extern int ripng_passive_interface_set(const char *ifname);
|
||||
extern int ripng_passive_interface_unset(const char *ifname);
|
||||
extern void ripng_passive_interface_clean(void);
|
||||
extern void ripng_clean(struct ripng *ripng);
|
||||
extern void ripng_clean_network(struct ripng *ripng);
|
||||
extern void ripng_interface_clean(struct ripng *ripng);
|
||||
extern int ripng_enable_network_add(struct ripng *ripng, struct prefix *p);
|
||||
extern int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p);
|
||||
extern int ripng_enable_if_add(struct ripng *ripng, const char *ifname);
|
||||
extern int ripng_enable_if_delete(struct ripng *ripng, const char *ifname);
|
||||
extern int ripng_passive_interface_set(struct ripng *ripng, const char *ifname);
|
||||
extern int ripng_passive_interface_unset(struct ripng *ripng,
|
||||
const char *ifname);
|
||||
extern void ripng_passive_interface_clean(struct ripng *ripng);
|
||||
extern void ripng_if_init(void);
|
||||
extern void ripng_route_map_init(void);
|
||||
extern void ripng_zebra_vrf_register(struct vrf *vrf);
|
||||
extern void ripng_zebra_vrf_deregister(struct vrf *vrf);
|
||||
extern void ripng_terminate(void);
|
||||
/* zclient_init() is done by ripng_zebra.c:zebra_init() */
|
||||
extern void zebra_init(struct thread_master *);
|
||||
extern void ripng_zebra_stop(void);
|
||||
extern void ripng_redistribute_conf_update(int type);
|
||||
extern void ripng_redistribute_conf_delete(int type);
|
||||
extern void ripng_redistribute_conf_update(struct ripng *ripng, int type);
|
||||
extern void ripng_redistribute_conf_delete(struct ripng *ripng, int type);
|
||||
|
||||
extern void ripng_peer_init(void);
|
||||
extern void ripng_peer_update(struct sockaddr_in6 *, uint8_t);
|
||||
extern void ripng_peer_bad_route(struct sockaddr_in6 *);
|
||||
extern void ripng_peer_bad_packet(struct sockaddr_in6 *);
|
||||
extern void ripng_peer_display(struct vty *);
|
||||
extern struct ripng_peer *ripng_peer_lookup(struct in6_addr *);
|
||||
extern struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *);
|
||||
extern void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from,
|
||||
uint8_t version);
|
||||
extern void ripng_peer_bad_route(struct ripng *ripng,
|
||||
struct sockaddr_in6 *from);
|
||||
extern void ripng_peer_bad_packet(struct ripng *ripng,
|
||||
struct sockaddr_in6 *from);
|
||||
extern void ripng_peer_display(struct vty *vty, struct ripng *ripng);
|
||||
extern struct ripng_peer *ripng_peer_lookup(struct ripng *ripng,
|
||||
struct in6_addr *addr);
|
||||
extern struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng,
|
||||
struct in6_addr *addr);
|
||||
extern int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2);
|
||||
extern void ripng_peer_list_del(void *arg);
|
||||
|
||||
extern struct ripng_offset_list *ripng_offset_list_new(const char *ifname);
|
||||
extern struct ripng_offset_list *ripng_offset_list_new(struct ripng *ripng,
|
||||
const char *ifname);
|
||||
extern void ripng_offset_list_del(struct ripng_offset_list *offset);
|
||||
extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
|
||||
extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
|
||||
extern int ripng_offset_list_apply_in(struct prefix_ipv6 *, struct interface *,
|
||||
uint8_t *);
|
||||
extern int ripng_offset_list_apply_out(struct prefix_ipv6 *, struct interface *,
|
||||
uint8_t *);
|
||||
extern void ripng_offset_init(void);
|
||||
extern void ripng_offset_clean(void);
|
||||
extern struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng,
|
||||
const char *ifname);
|
||||
extern int ripng_offset_list_apply_in(struct ripng *ripng,
|
||||
struct prefix_ipv6 *p,
|
||||
struct interface *ifp, uint8_t *metric);
|
||||
extern int ripng_offset_list_apply_out(struct ripng *ripng,
|
||||
struct prefix_ipv6 *p,
|
||||
struct interface *ifp, uint8_t *metric);
|
||||
extern int offset_list_cmp(struct ripng_offset_list *o1,
|
||||
struct ripng_offset_list *o2);
|
||||
|
||||
extern int ripng_route_rte(struct ripng_info *rinfo);
|
||||
extern struct ripng_info *ripng_info_new(void);
|
||||
extern void ripng_info_free(struct ripng_info *rinfo);
|
||||
extern void ripng_event(enum ripng_event, int);
|
||||
extern struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo);
|
||||
extern void ripng_event(struct ripng *ripng, enum ripng_event event, int sock);
|
||||
extern int ripng_request(struct interface *ifp);
|
||||
extern void ripng_redistribute_add(int, int, struct prefix_ipv6 *, ifindex_t,
|
||||
struct in6_addr *, route_tag_t);
|
||||
extern void ripng_redistribute_delete(int, int, struct prefix_ipv6 *,
|
||||
ifindex_t);
|
||||
extern void ripng_redistribute_withdraw(int type);
|
||||
extern void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type,
|
||||
struct prefix_ipv6 *p, ifindex_t ifindex,
|
||||
struct in6_addr *nexthop, route_tag_t tag);
|
||||
extern void ripng_redistribute_delete(struct ripng *ripng, int type,
|
||||
int sub_type, struct prefix_ipv6 *p,
|
||||
ifindex_t ifindex);
|
||||
extern void ripng_redistribute_withdraw(struct ripng *ripng, int type);
|
||||
|
||||
extern void ripng_ecmp_disable(void);
|
||||
extern void ripng_ecmp_disable(struct ripng *ripng);
|
||||
extern void ripng_distribute_update_interface(struct interface *);
|
||||
extern void ripng_if_rmap_update_interface(struct interface *);
|
||||
|
||||
extern void ripng_zebra_ipv6_add(struct agg_node *node);
|
||||
extern void ripng_zebra_ipv6_delete(struct agg_node *node);
|
||||
extern void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *node);
|
||||
extern void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *node);
|
||||
|
||||
extern void ripng_redistribute_clean(void);
|
||||
extern int ripng_redistribute_check(int);
|
||||
extern void ripng_redistribute_write(struct vty *);
|
||||
extern void ripng_redistribute_enable(struct ripng *ripng);
|
||||
extern void ripng_redistribute_disable(struct ripng *ripng);
|
||||
extern int ripng_redistribute_check(struct ripng *ripng, int type);
|
||||
extern void ripng_redistribute_write(struct vty *vty, struct ripng *ripng);
|
||||
|
||||
extern int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p,
|
||||
struct in6_addr *nexthop, uint16_t tag,
|
||||
@ -423,14 +479,26 @@ extern int ripng_interface_address_add(int command, struct zclient *,
|
||||
zebra_size_t, vrf_id_t);
|
||||
extern int ripng_interface_address_delete(int command, struct zclient *,
|
||||
zebra_size_t, vrf_id_t);
|
||||
extern int ripng_interface_vrf_update(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id);
|
||||
extern void ripng_interface_sync(struct interface *ifp);
|
||||
|
||||
extern int ripng_create(int socket);
|
||||
extern int ripng_make_socket(void);
|
||||
extern int ripng_network_write(struct vty *);
|
||||
extern struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id);
|
||||
extern struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name);
|
||||
extern struct ripng *ripng_create(const char *vrf_name, struct vrf *vrf,
|
||||
int socket);
|
||||
extern int ripng_make_socket(struct vrf *vrf);
|
||||
extern int ripng_network_write(struct vty *vty, struct ripng *ripng);
|
||||
|
||||
extern struct ripng_info *ripng_ecmp_add(struct ripng_info *);
|
||||
extern struct ripng_info *ripng_ecmp_replace(struct ripng_info *);
|
||||
extern struct ripng_info *ripng_ecmp_delete(struct ripng_info *);
|
||||
extern struct ripng_info *ripng_ecmp_add(struct ripng *ripng,
|
||||
struct ripng_info *rinfo);
|
||||
extern struct ripng_info *ripng_ecmp_replace(struct ripng *ripng,
|
||||
struct ripng_info *rinfo);
|
||||
extern struct ripng_info *ripng_ecmp_delete(struct ripng *ripng,
|
||||
struct ripng_info *rinfo);
|
||||
|
||||
extern void ripng_vrf_init(void);
|
||||
extern void ripng_vrf_terminate(void);
|
||||
|
||||
/* Northbound. */
|
||||
extern void ripng_cli_init(void);
|
||||
|
@ -1521,15 +1521,15 @@ DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)",
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip",
|
||||
ROUTER_STR "RIP\n")
|
||||
DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]",
|
||||
ROUTER_STR "RIP\n" VRF_CMD_HELP_STR)
|
||||
{
|
||||
vty->node = RIP_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng",
|
||||
ROUTER_STR "RIPng\n")
|
||||
DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]",
|
||||
ROUTER_STR "RIPng\n" VRF_CMD_HELP_STR)
|
||||
{
|
||||
vty->node = RIPNG_NODE;
|
||||
return CMD_SUCCESS;
|
||||
|
@ -20,25 +20,28 @@
|
||||
]
|
||||
},
|
||||
"frr-ripd:ripd": {
|
||||
"instance": {
|
||||
"instance": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"allow-ecmp": "true",
|
||||
"distance": {
|
||||
"source": [
|
||||
{
|
||||
"prefix": "172.16.1.0/24",
|
||||
"distance": "25"
|
||||
"distance": "25",
|
||||
"prefix": "172.16.1.0/24"
|
||||
}
|
||||
]
|
||||
},
|
||||
"redistribute": [
|
||||
{
|
||||
"protocol": "ospf",
|
||||
"metric": "3"
|
||||
"metric": "3",
|
||||
"protocol": "ospf"
|
||||
}
|
||||
],
|
||||
"static-route": [
|
||||
"10.0.1.0/24"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
</lib>
|
||||
<ripd xmlns="http://frrouting.org/yang/ripd">
|
||||
<instance>
|
||||
<vrf>default</vrf>
|
||||
<allow-ecmp>true</allow-ecmp>
|
||||
<static-route>10.0.1.0/24</static-route>
|
||||
<distance>
|
||||
|
@ -34,13 +34,18 @@ module frr-ripd {
|
||||
|
||||
container ripd {
|
||||
/*
|
||||
* Global configuration data
|
||||
* Routing instance configuration.
|
||||
*/
|
||||
container instance {
|
||||
presence "Present if the RIP protocol is enabled.";
|
||||
list instance {
|
||||
key "vrf";
|
||||
description
|
||||
"RIP routing instance.";
|
||||
|
||||
leaf vrf {
|
||||
type string;
|
||||
description
|
||||
"VRF name.";
|
||||
}
|
||||
leaf allow-ecmp {
|
||||
type boolean;
|
||||
default "false";
|
||||
@ -293,7 +298,6 @@ module frr-ripd {
|
||||
'(./receive = "2" and ./send = "2") or ' +
|
||||
'(./receive = "1-2" and ./send = "2")';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Operational data.
|
||||
@ -375,6 +379,7 @@ module frr-ripd {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Per-interface configuration data
|
||||
@ -547,6 +552,19 @@ module frr-ripd {
|
||||
description
|
||||
"Clears RIP routes from the IP routing table and routes
|
||||
redistributed into the RIP protocol.";
|
||||
|
||||
input {
|
||||
leaf vrf {
|
||||
type string;
|
||||
description
|
||||
"VRF name identifying a specific RIP instance.
|
||||
This leaf is optional for the rpc.
|
||||
If it is specified, the rpc will clear all routes in the
|
||||
specified RIP instance;
|
||||
if it is not specified, the rpc will clear all routes in
|
||||
all RIP instances.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -33,13 +33,18 @@ module frr-ripngd {
|
||||
|
||||
container ripngd {
|
||||
/*
|
||||
* Global configuration data
|
||||
* Routing instance configuration.
|
||||
*/
|
||||
container instance {
|
||||
presence "Present if the RIPng protocol is enabled.";
|
||||
list instance {
|
||||
key "vrf";
|
||||
description
|
||||
"RIPng routing instance.";
|
||||
|
||||
leaf vrf {
|
||||
type string;
|
||||
description
|
||||
"VRF name.";
|
||||
}
|
||||
leaf allow-ecmp {
|
||||
type boolean;
|
||||
default "false";
|
||||
@ -194,7 +199,6 @@ module frr-ripngd {
|
||||
"Interval at which RIPng updates are sent.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Operational data.
|
||||
@ -275,6 +279,7 @@ module frr-ripngd {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Per-interface configuration data
|
||||
@ -317,5 +322,18 @@ module frr-ripngd {
|
||||
description
|
||||
"Clears RIPng routes from the IPv6 routing table and routes
|
||||
redistributed into the RIPng protocol.";
|
||||
|
||||
input {
|
||||
leaf vrf {
|
||||
type string;
|
||||
description
|
||||
"VRF name identifying a specific RIPng instance.
|
||||
This leaf is optional for the rpc.
|
||||
If it is specified, the rpc will clear all routes in the
|
||||
specified RIPng instance;
|
||||
if it is not specified, the rpc will clear all routes in
|
||||
all RIPng instances.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
"mappings": [
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']",
|
||||
"native": "/frr-ripd:ripd/instance"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -32,31 +32,31 @@
|
||||
"mappings": [
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/default-metric",
|
||||
"native": "/frr-ripd:ripd/instance/default-metric"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/default-metric"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/distance",
|
||||
"native": "/frr-ripd:ripd/instance/distance/default"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/distance/default"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/originate-default-route/enabled",
|
||||
"native": "/frr-ripd:ripd/instance/default-information-originate"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/default-information-originate"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/update-interval",
|
||||
"native": "/frr-ripd:ripd/instance/timers/update-interval"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/timers/update-interval"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/holddown-interval",
|
||||
"native": "/frr-ripd:ripd/instance/timers/holddown-interval"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/timers/holddown-interval"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/flush-interval",
|
||||
"native": "/frr-ripd:ripd/instance/timers/flush-interval"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/timers/flush-interval"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/interfaces/interface[interface='KEY1']",
|
||||
"native": "/frr-ripd:ripd/instance/interface[.='KEY1']"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/interface[.='KEY1']"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/interfaces/interface[interface='KEY1']/split-horizon",
|
||||
@ -64,43 +64,43 @@
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']",
|
||||
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/ipv4-address",
|
||||
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/address"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/address"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/last-update",
|
||||
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/last-update"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/last-update"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/bad-packets-rcvd",
|
||||
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/bad-packets-rcvd"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/bad-packets-rcvd"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/bad-routes-rcvd",
|
||||
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/bad-routes-rcvd"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/bad-routes-rcvd"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']",
|
||||
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/ipv4-prefix",
|
||||
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/prefix"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/prefix"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/next-hop",
|
||||
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/next-hop"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/next-hop"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/interface",
|
||||
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/interface"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/interface"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/metric",
|
||||
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/metric"
|
||||
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/metric"
|
||||
},
|
||||
{
|
||||
"custom": "/ietf-rip:clear-rip-route",
|
||||
|
Loading…
Reference in New Issue
Block a user