mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 20:55:25 +00:00
Merge pull request #3548 from opensourcerouting/rip-vrf
rip(ng)d: add VRF support
This commit is contained in:
commit
f61f266a0e
12
lib/if.c
12
lib/if.c
@ -1310,8 +1310,8 @@ static int lib_interface_create(enum nb_event event,
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int lib_interface_delete(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
static int lib_interface_destroy(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
struct interface *ifp;
|
||||
|
||||
@ -1357,8 +1357,8 @@ static int lib_interface_description_modify(enum nb_event event,
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
static int lib_interface_description_delete(enum nb_event event,
|
||||
const struct lyd_node *dnode)
|
||||
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,61 +1145,64 @@ 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;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
struct lyd_node *dnode;
|
||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||
struct interface *ifp;
|
||||
|
||||
dnode = yang_dnode_get(
|
||||
running_config->dnode,
|
||||
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
|
||||
ifp->name, vrf->name);
|
||||
if (dnode == NULL)
|
||||
continue;
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
struct lyd_node *dnode;
|
||||
|
||||
write = 1;
|
||||
nb_cli_show_dnode_cmds(vty, dnode, false);
|
||||
dnode = yang_dnode_get(
|
||||
running_config->dnode,
|
||||
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
|
||||
ifp->name, vrf->name);
|
||||
if (dnode == NULL)
|
||||
continue;
|
||||
|
||||
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;
|
||||
}
|
||||
|
898
ripd/ripd.c
898
ripd/ripd.c
File diff suppressed because it is too large
Load Diff
190
ripd/ripd.h
190
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 {
|
||||
char *name;
|
||||
struct route_map *map;
|
||||
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,22 +964,25 @@ 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;
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
struct lyd_node *dnode;
|
||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||
struct interface *ifp;
|
||||
|
||||
dnode = yang_dnode_get(
|
||||
running_config->dnode,
|
||||
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
|
||||
ifp->name, vrf->name);
|
||||
if (dnode == NULL)
|
||||
continue;
|
||||
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||
struct lyd_node *dnode;
|
||||
|
||||
write = 1;
|
||||
nb_cli_show_dnode_cmds(vty, dnode, false);
|
||||
dnode = yang_dnode_get(
|
||||
running_config->dnode,
|
||||
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
|
||||
ifp->name, vrf->name);
|
||||
if (dnode == NULL)
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
721
ripngd/ripngd.c
721
ripngd/ripngd.c
File diff suppressed because it is too large
Load Diff
172
ripngd/ripngd.h
172
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 {
|
||||
char *name;
|
||||
struct route_map *map;
|
||||
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": {
|
||||
"allow-ecmp": "true",
|
||||
"distance": {
|
||||
"source": [
|
||||
"instance": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"allow-ecmp": "true",
|
||||
"distance": {
|
||||
"source": [
|
||||
{
|
||||
"distance": "25",
|
||||
"prefix": "172.16.1.0/24"
|
||||
}
|
||||
]
|
||||
},
|
||||
"redistribute": [
|
||||
{
|
||||
"prefix": "172.16.1.0/24",
|
||||
"distance": "25"
|
||||
"metric": "3",
|
||||
"protocol": "ospf"
|
||||
}
|
||||
],
|
||||
"static-route": [
|
||||
"10.0.1.0/24"
|
||||
]
|
||||
},
|
||||
"redistribute": [
|
||||
{
|
||||
"protocol": "ospf",
|
||||
"metric": "3"
|
||||
}
|
||||
],
|
||||
"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,83 +298,83 @@ module frr-ripd {
|
||||
'(./receive = "2" and ./send = "2") or ' +
|
||||
'(./receive = "1-2" and ./send = "2")';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Operational data.
|
||||
*/
|
||||
container state {
|
||||
config false;
|
||||
description
|
||||
"Operational data.";
|
||||
|
||||
container neighbors {
|
||||
/*
|
||||
* Operational data.
|
||||
*/
|
||||
container state {
|
||||
config false;
|
||||
description
|
||||
"Neighbor information.";
|
||||
list neighbor {
|
||||
key "address";
|
||||
"Operational data.";
|
||||
|
||||
container neighbors {
|
||||
description
|
||||
"A RIP neighbor.";
|
||||
leaf address {
|
||||
type inet:ipv4-address;
|
||||
"Neighbor information.";
|
||||
list neighbor {
|
||||
key "address";
|
||||
description
|
||||
"IP address that a RIP neighbor is using as its
|
||||
source address.";
|
||||
}
|
||||
leaf last-update {
|
||||
type yang:date-and-time;
|
||||
description
|
||||
"The time when the most recent RIP update was
|
||||
received from this neighbor.";
|
||||
}
|
||||
leaf bad-packets-rcvd {
|
||||
type yang:counter32;
|
||||
description
|
||||
"The number of RIP invalid packets received from
|
||||
this neighbor which were subsequently discarded
|
||||
for any reason (e.g. a version 0 packet, or an
|
||||
unknown command type).";
|
||||
}
|
||||
leaf bad-routes-rcvd {
|
||||
type yang:counter32;
|
||||
description
|
||||
"The number of routes received from this neighbor,
|
||||
in valid RIP packets, which were ignored for any
|
||||
reason (e.g. unknown address family, or invalid
|
||||
metric).";
|
||||
"A RIP neighbor.";
|
||||
leaf address {
|
||||
type inet:ipv4-address;
|
||||
description
|
||||
"IP address that a RIP neighbor is using as its
|
||||
source address.";
|
||||
}
|
||||
leaf last-update {
|
||||
type yang:date-and-time;
|
||||
description
|
||||
"The time when the most recent RIP update was
|
||||
received from this neighbor.";
|
||||
}
|
||||
leaf bad-packets-rcvd {
|
||||
type yang:counter32;
|
||||
description
|
||||
"The number of RIP invalid packets received from
|
||||
this neighbor which were subsequently discarded
|
||||
for any reason (e.g. a version 0 packet, or an
|
||||
unknown command type).";
|
||||
}
|
||||
leaf bad-routes-rcvd {
|
||||
type yang:counter32;
|
||||
description
|
||||
"The number of routes received from this neighbor,
|
||||
in valid RIP packets, which were ignored for any
|
||||
reason (e.g. unknown address family, or invalid
|
||||
metric).";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
container routes {
|
||||
description
|
||||
"Route information.";
|
||||
list route {
|
||||
key "prefix";
|
||||
container routes {
|
||||
description
|
||||
"A RIP IPv4 route.";
|
||||
leaf prefix {
|
||||
type inet:ipv4-prefix;
|
||||
"Route information.";
|
||||
list route {
|
||||
key "prefix";
|
||||
description
|
||||
"IP address (in the form A.B.C.D) and prefix length,
|
||||
separated by the slash (/) character. The range of
|
||||
values for the prefix-length is 0 to 32.";
|
||||
}
|
||||
leaf next-hop {
|
||||
type inet:ipv4-address;
|
||||
description
|
||||
"Next hop IPv4 address.";
|
||||
}
|
||||
leaf interface {
|
||||
type string;
|
||||
description
|
||||
"The interface that the route uses.";
|
||||
}
|
||||
leaf metric {
|
||||
type uint8 {
|
||||
range "0..16";
|
||||
"A RIP IPv4 route.";
|
||||
leaf prefix {
|
||||
type inet:ipv4-prefix;
|
||||
description
|
||||
"IP address (in the form A.B.C.D) and prefix length,
|
||||
separated by the slash (/) character. The range of
|
||||
values for the prefix-length is 0 to 32.";
|
||||
}
|
||||
leaf next-hop {
|
||||
type inet:ipv4-address;
|
||||
description
|
||||
"Next hop IPv4 address.";
|
||||
}
|
||||
leaf interface {
|
||||
type string;
|
||||
description
|
||||
"The interface that the route uses.";
|
||||
}
|
||||
leaf metric {
|
||||
type uint8 {
|
||||
range "0..16";
|
||||
}
|
||||
description
|
||||
"Route metric.";
|
||||
}
|
||||
description
|
||||
"Route metric.";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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,82 +199,82 @@ module frr-ripngd {
|
||||
"Interval at which RIPng updates are sent.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Operational data.
|
||||
*/
|
||||
container state {
|
||||
config false;
|
||||
description
|
||||
"Operational data.";
|
||||
|
||||
container neighbors {
|
||||
/*
|
||||
* Operational data.
|
||||
*/
|
||||
container state {
|
||||
config false;
|
||||
description
|
||||
"Neighbor information.";
|
||||
list neighbor {
|
||||
key "address";
|
||||
"Operational data.";
|
||||
|
||||
container neighbors {
|
||||
description
|
||||
"A RIPng neighbor.";
|
||||
leaf address {
|
||||
type inet:ipv6-address;
|
||||
"Neighbor information.";
|
||||
list neighbor {
|
||||
key "address";
|
||||
description
|
||||
"IPv6 address that a RIPng neighbor is using as its
|
||||
source address.";
|
||||
}
|
||||
leaf last-update {
|
||||
type yang:date-and-time;
|
||||
description
|
||||
"The time when the most recent RIPng update was
|
||||
received from this neighbor.";
|
||||
}
|
||||
leaf bad-packets-rcvd {
|
||||
type yang:counter32;
|
||||
description
|
||||
"The number of RIPng invalid packets received from
|
||||
this neighbor which were subsequently discarded
|
||||
for any reason (e.g. a version 0 packet, or an
|
||||
unknown command type).";
|
||||
}
|
||||
leaf bad-routes-rcvd {
|
||||
type yang:counter32;
|
||||
description
|
||||
"The number of routes received from this neighbor,
|
||||
in valid RIPng packets, which were ignored for any
|
||||
reason (e.g. unknown address family, or invalid
|
||||
metric).";
|
||||
"A RIPng neighbor.";
|
||||
leaf address {
|
||||
type inet:ipv6-address;
|
||||
description
|
||||
"IPv6 address that a RIPng neighbor is using as its
|
||||
source address.";
|
||||
}
|
||||
leaf last-update {
|
||||
type yang:date-and-time;
|
||||
description
|
||||
"The time when the most recent RIPng update was
|
||||
received from this neighbor.";
|
||||
}
|
||||
leaf bad-packets-rcvd {
|
||||
type yang:counter32;
|
||||
description
|
||||
"The number of RIPng invalid packets received from
|
||||
this neighbor which were subsequently discarded
|
||||
for any reason (e.g. a version 0 packet, or an
|
||||
unknown command type).";
|
||||
}
|
||||
leaf bad-routes-rcvd {
|
||||
type yang:counter32;
|
||||
description
|
||||
"The number of routes received from this neighbor,
|
||||
in valid RIPng packets, which were ignored for any
|
||||
reason (e.g. unknown address family, or invalid
|
||||
metric).";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
container routes {
|
||||
description
|
||||
"Route information.";
|
||||
list route {
|
||||
key "prefix";
|
||||
container routes {
|
||||
description
|
||||
"A RIPng IPv6 route.";
|
||||
leaf prefix {
|
||||
type inet:ipv6-prefix;
|
||||
"Route information.";
|
||||
list route {
|
||||
key "prefix";
|
||||
description
|
||||
"IPv6 address and prefix length, in the format
|
||||
specified in RFC6991.";
|
||||
}
|
||||
leaf next-hop {
|
||||
type inet:ipv6-address;
|
||||
description
|
||||
"Next hop IPv6 address.";
|
||||
}
|
||||
leaf interface {
|
||||
type string;
|
||||
description
|
||||
"The interface that the route uses.";
|
||||
}
|
||||
leaf metric {
|
||||
type uint8 {
|
||||
range "0..16";
|
||||
"A RIPng IPv6 route.";
|
||||
leaf prefix {
|
||||
type inet:ipv6-prefix;
|
||||
description
|
||||
"IPv6 address and prefix length, in the format
|
||||
specified in RFC6991.";
|
||||
}
|
||||
leaf next-hop {
|
||||
type inet:ipv6-address;
|
||||
description
|
||||
"Next hop IPv6 address.";
|
||||
}
|
||||
leaf interface {
|
||||
type string;
|
||||
description
|
||||
"The interface that the route uses.";
|
||||
}
|
||||
leaf metric {
|
||||
type uint8 {
|
||||
range "0..16";
|
||||
}
|
||||
description
|
||||
"Route metric.";
|
||||
}
|
||||
description
|
||||
"Route metric.";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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