diff options
-rw-r--r-- | ripd/rip_interface.c | 134 | ||||
-rw-r--r-- | ripd/rip_main.c | 11 | ||||
-rw-r--r-- | ripd/rip_northbound.c | 146 | ||||
-rw-r--r-- | ripd/rip_offset.c | 18 | ||||
-rw-r--r-- | ripd/rip_peer.c | 25 | ||||
-rw-r--r-- | ripd/rip_snmp.c | 19 | ||||
-rw-r--r-- | ripd/rip_zebra.c | 47 | ||||
-rw-r--r-- | ripd/ripd.c | 343 | ||||
-rw-r--r-- | ripd/ripd.h | 114 |
9 files changed, 538 insertions, 319 deletions
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 2e432ec79..ca6dea1b3 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -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"}, @@ -94,12 +94,17 @@ static int ipv4_multicast_leave(int sock, struct in_addr group, static void rip_interface_reset(struct rip_interface *); /* Allocate new RIP's interface configuration. */ -static struct rip_interface *rip_interface_new(void) +static struct rip_interface *rip_interface_new(struct interface *ifp) { + struct vrf *vrf; struct rip_interface *ri; ri = XCALLOC(MTYPE_RIP_INTERFACE, sizeof(struct rip_interface)); + vrf = vrf_lookup_by_id(ifp->vrf_id); + if (vrf) + ri->rip = vrf->info; + rip_interface_reset(ri); return ri; @@ -199,7 +204,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); @@ -320,9 +325,9 @@ 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 vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) { @@ -474,9 +479,9 @@ 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 vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) @@ -524,20 +529,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) @@ -555,6 +562,8 @@ int rip_if_down(struct interface *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; @@ -580,10 +589,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, @@ -617,6 +627,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; @@ -634,7 +646,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); } @@ -672,6 +684,8 @@ 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; @@ -702,8 +716,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; @@ -730,7 +746,7 @@ 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; @@ -743,13 +759,13 @@ 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; @@ -764,7 +780,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; } @@ -773,7 +789,7 @@ 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; @@ -789,29 +805,29 @@ static int rip_enable_if_lookup(const char *ifname) } /* 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, 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; @@ -819,7 +835,7 @@ int rip_enable_if_delete(const char *ifname) XFREE(MTYPE_RIP_INTERFACE_STRING, str); vector_unset(rip->enable_interface, index); - rip_enable_apply_all(); /* TODOVJ */ + rip_enable_apply_all(rip); /* TODOVJ */ return NB_OK; } @@ -837,7 +853,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); @@ -855,6 +871,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; @@ -879,17 +897,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); } @@ -918,7 +937,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 @@ -951,9 +970,9 @@ void rip_enable_apply(struct interface *ifp) } /* Apply network configuration to all interface. */ -void rip_enable_apply_all() +static void rip_enable_apply_all(struct rip *rip) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; /* Check each interface. */ @@ -961,7 +980,7 @@ void rip_enable_apply_all() 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; @@ -980,7 +999,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; @@ -995,7 +1014,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; @@ -1016,7 +1035,7 @@ int rip_neighbor_delete(struct prefix_ipv4 *p) } /* Clear all network and neighbor configuration. */ -void rip_clean_network() +void rip_clean_network(struct rip *rip) { unsigned int i; char *str; @@ -1038,7 +1057,7 @@ void rip_clean_network() } /* 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; @@ -1050,16 +1069,17 @@ static int rip_passive_nondefault_lookup(const char *ifname) 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); @@ -1068,9 +1088,9 @@ 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 vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) @@ -1078,9 +1098,9 @@ static void rip_passive_interface_apply_all(void) } /* 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'. @@ -1090,17 +1110,17 @@ int rip_passive_nondefault_set(const char *ifname) 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 @@ -1112,13 +1132,13 @@ int rip_passive_nondefault_unset(const char *ifname) XFREE(MTYPE_RIP_INTERFACE_STRING, str); 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; @@ -1128,7 +1148,7 @@ void rip_passive_nondefault_clean(void) XFREE(MTYPE_RIP_INTERFACE_STRING, str); vector_slot(rip->passive_nondefault, i) = NULL; } - rip_passive_interface_apply_all(); + rip_passive_interface_apply_all(rip); } /* Write rip configuration of each interface. */ @@ -1155,7 +1175,7 @@ static int rip_interface_config_write(struct vty *vty) 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; @@ -1189,7 +1209,7 @@ static struct cmd_node interface_node = { /* Called when interface structure allocated. */ static int rip_interface_new_hook(struct interface *ifp) { - ifp->info = rip_interface_new(); + ifp->info = rip_interface_new(ifp); return 0; } diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 8c6340f6c..46babe2e0 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -79,10 +79,17 @@ static void sighup(void) /* SIGINT handler. */ static void sigint(void) { + struct vrf *vrf; + zlog_notice("Terminating on signal"); - if (rip) - rip_clean(); + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { + struct rip *rip; + + rip = vrf->info; + if (rip) + rip_clean(rip); + } rip_zclient_stop(); frr_fini(); diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index b0f2b62a5..f5a75707e 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -40,6 +40,8 @@ static int ripd_instance_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + struct vrf *vrf; int socket; switch (event) { @@ -56,8 +58,10 @@ static int ripd_instance_create(enum nb_event event, close(socket); break; case NB_EV_APPLY: + vrf = vrf_lookup_by_id(VRF_DEFAULT); socket = resource->fd; - rip_create(socket); + rip = rip_create(vrf, socket); + yang_dnode_set_entry(dnode, rip); break; } @@ -67,10 +71,13 @@ static int ripd_instance_create(enum nb_event event, static int ripd_instance_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; - rip_clean(); + rip = yang_dnode_get_entry(dnode, true); + rip_clean(rip); return NB_OK; } @@ -82,12 +89,15 @@ static int ripd_instance_allow_ecmp_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->ecmp = yang_dnode_get_bool(dnode, NULL); if (!rip->ecmp) - rip_ecmp_disable(); + rip_ecmp_disable(rip); return NB_OK; } @@ -100,12 +110,14 @@ ripd_instance_default_information_originate_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; bool default_information; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); default_information = yang_dnode_get_bool(dnode, NULL); memset(&p, 0, sizeof(struct prefix_ipv4)); @@ -115,11 +127,11 @@ ripd_instance_default_information_originate_modify(enum nb_event event, memset(&nh, 0, sizeof(nh)); nh.type = NEXTHOP_TYPE_IPV4; - rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, - &nh, 0, 0, 0); + rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, + &p, &nh, 0, 0, 0); } else { - rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, - 0); + rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, + &p, 0); } return NB_OK; @@ -132,9 +144,12 @@ static int ripd_instance_default_metric_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->default_metric = yang_dnode_get_uint8(dnode, NULL); /* rip_update_default_metric (); */ @@ -148,9 +163,12 @@ static int ripd_instance_distance_default_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->distance = yang_dnode_get_uint8(dnode, NULL); return NB_OK; @@ -163,6 +181,7 @@ static int ripd_instance_distance_source_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; struct prefix_ipv4 prefix; struct route_node *rn; @@ -173,6 +192,7 @@ static int ripd_instance_distance_source_create(enum nb_event event, apply_mask_ipv4(&prefix); /* Get RIP distance node. */ + rip = yang_dnode_get_entry(dnode, true); rn = route_node_get(rip->distance_table, (struct prefix *)&prefix); rn->info = rip_distance_new(); yang_dnode_set_entry(dnode, rn); @@ -275,31 +295,35 @@ static int ripd_instance_explicit_neighbor_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; yang_dnode_get_ipv4(&p.prefix, dnode, NULL); - return rip_neighbor_add(&p); + return rip_neighbor_add(rip, &p); } static int ripd_instance_explicit_neighbor_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; yang_dnode_get_ipv4(&p.prefix, dnode, NULL); - return rip_neighbor_delete(&p); + return rip_neighbor_delete(rip, &p); } /* @@ -309,29 +333,33 @@ static int ripd_instance_network_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; struct prefix p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv4p(&p, dnode, NULL); apply_mask_ipv4((struct prefix_ipv4 *)&p); - return rip_enable_network_add(&p); + return rip_enable_network_add(rip, &p); } static int ripd_instance_network_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; struct prefix p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv4p(&p, dnode, NULL); apply_mask_ipv4((struct prefix_ipv4 *)&p); - return rip_enable_network_delete(&p); + return rip_enable_network_delete(rip, &p); } /* @@ -341,27 +369,31 @@ static int ripd_instance_interface_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_enable_if_add(ifname); + return rip_enable_if_add(rip, ifname); } static int ripd_instance_interface_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_enable_if_delete(ifname); + return rip_enable_if_delete(rip, ifname); } /* @@ -371,15 +403,17 @@ static int ripd_instance_offset_list_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; const char *ifname; struct rip_offset_list *offset; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, "./interface"); - offset = rip_offset_list_new(ifname); + offset = rip_offset_list_new(rip, ifname); yang_dnode_set_entry(dnode, offset); return NB_OK; @@ -464,11 +498,14 @@ static int ripd_instance_passive_default_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->passive_default = yang_dnode_get_bool(dnode, NULL); - rip_passive_nondefault_clean(); + rip_passive_nondefault_clean(rip); return NB_OK; } @@ -480,27 +517,31 @@ static int ripd_instance_passive_interface_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_passive_nondefault_set(ifname); + return rip_passive_nondefault_set(rip, ifname); } static int ripd_instance_passive_interface_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_passive_nondefault_unset(ifname); + return rip_passive_nondefault_unset(rip, ifname); } /* @@ -511,28 +552,32 @@ ripd_instance_non_passive_interface_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_passive_nondefault_unset(ifname); + return rip_passive_nondefault_unset(rip, ifname); } static int ripd_instance_non_passive_interface_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_passive_nondefault_set(ifname); + return rip_passive_nondefault_set(rip, ifname); } /* @@ -548,14 +593,16 @@ static int ripd_instance_redistribute_create(enum nb_event event, static int ripd_instance_redistribute_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; int type; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "./protocol"); - rip_redistribute_conf_delete(type); + rip_redistribute_conf_delete(rip, type); return NB_OK; } @@ -563,10 +610,13 @@ static int ripd_instance_redistribute_delete(enum nb_event event, static void ripd_instance_redistribute_apply_finish(const struct lyd_node *dnode) { + struct rip *rip; int type; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "./protocol"); - rip_redistribute_conf_update(type); + + rip_redistribute_conf_update(rip, type); } /* @@ -577,12 +627,14 @@ ripd_instance_redistribute_route_map_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; int type; const char *rmap_name; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); rmap_name = yang_dnode_get_string(dnode, NULL); @@ -598,11 +650,13 @@ static int ripd_instance_redistribute_route_map_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; int type; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); free(rip->route_map[type].name); @@ -620,12 +674,14 @@ ripd_instance_redistribute_metric_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; int type; uint8_t metric; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); metric = yang_dnode_get_uint8(dnode, NULL); @@ -639,11 +695,13 @@ static int ripd_instance_redistribute_metric_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; int type; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); rip->route_map[type].metric_config = false; @@ -659,19 +717,21 @@ static int ripd_instance_static_route_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; struct nexthop nh; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv4p(&p, dnode, NULL); apply_mask_ipv4(&p); memset(&nh, 0, sizeof(nh)); nh.type = NEXTHOP_TYPE_IPV4; - rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0, 0, - 0); + rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0, + 0, 0); return NB_OK; } @@ -679,15 +739,17 @@ static int ripd_instance_static_route_create(enum nb_event event, static int ripd_instance_static_route_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv4p(&p, dnode, NULL); apply_mask_ipv4(&p); - rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); + rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); return NB_OK; } @@ -697,8 +759,12 @@ static int ripd_instance_static_route_delete(enum nb_event event, */ static void ripd_instance_timers_apply_finish(const struct lyd_node *dnode) { + struct rip *rip; + + rip = yang_dnode_get_entry(dnode, true); + /* Reset update timer thread. */ - rip_event(RIP_UPDATE_EVENT, 0); + rip_event(rip, RIP_UPDATE_EVENT, 0); } /* @@ -709,9 +775,12 @@ ripd_instance_timers_flush_interval_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->garbage_time = yang_dnode_get_uint32(dnode, NULL); return NB_OK; @@ -725,9 +794,12 @@ ripd_instance_timers_holddown_interval_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->timeout_time = yang_dnode_get_uint32(dnode, NULL); return NB_OK; @@ -741,9 +813,12 @@ ripd_instance_timers_update_interval_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->update_time = yang_dnode_get_uint32(dnode, NULL); return NB_OK; @@ -756,9 +831,12 @@ static int ripd_instance_version_receive_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->version_recv = yang_dnode_get_enum(dnode, NULL); return NB_OK; @@ -771,9 +849,12 @@ static int ripd_instance_version_send_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->version_send = yang_dnode_get_enum(dnode, NULL); return NB_OK; @@ -1007,8 +1088,10 @@ static const void * ripd_state_neighbors_neighbor_get_next(const void *parent_list_entry, const void *list_entry) { + struct rip *rip; struct listnode *node; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (rip == NULL) return NULL; @@ -1037,12 +1120,14 @@ static const void * ripd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry, const struct yang_list_keys *keys) { + struct rip *rip; struct in_addr address; struct rip_peer *peer; struct listnode *node; yang_str2ipv4(keys->key[0], &address); + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (rip == NULL) return NULL; @@ -1111,8 +1196,10 @@ static const void * ripd_state_routes_route_get_next(const void *parent_list_entry, const void *list_entry) { + struct rip *rip; struct route_node *rn; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (rip == NULL) return NULL; @@ -1141,11 +1228,16 @@ static const void * ripd_state_routes_route_lookup_entry(const void *parent_list_entry, const struct yang_list_keys *keys) { + struct rip *rip; struct prefix prefix; struct route_node *rn; yang_str2ipv4p(keys->key[0], &prefix); + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); + if (rip == NULL) + return NULL; + rn = route_node_lookup(rip->table, &prefix); if (!rn || !rn->info) return NULL; @@ -1226,11 +1318,13 @@ ripd_state_routes_route_metric_get_elem(const char *xpath, static int clear_rip_route_rpc(const char *xpath, const struct list *input, struct list *output) { + struct rip *rip; struct route_node *rp; struct rip_info *rinfo; struct list *list; struct listnode *listnode; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (!rip) return NB_OK; @@ -1245,7 +1339,7 @@ static int clear_rip_route_rpc(const char *xpath, const struct list *input, continue; if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete(rp); + rip_zebra_ipv4_delete(rip, rp); break; } diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c index 94dc175d1..b3f84fe50 100644 --- a/ripd/rip_offset.c +++ b/ripd/rip_offset.c @@ -35,11 +35,12 @@ #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); @@ -48,7 +49,7 @@ struct rip_offset_list *rip_offset_list_new(const char *ifname) 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)) @@ -57,7 +58,8 @@ 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; @@ -73,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)); @@ -90,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)); @@ -109,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)); @@ -128,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)); diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index 07b295030..08aa61257 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -40,7 +40,7 @@ static void rip_peer_free(struct rip_peer *peer) 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; @@ -52,7 +52,7 @@ struct rip_peer *rip_peer_lookup(struct in_addr *addr) 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; @@ -70,24 +70,25 @@ static int rip_peer_timeout(struct thread *t) struct rip_peer *peer; peer = THREAD_ARG(t); - listnode_delete(rip->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(rip->peer_list, peer); } @@ -103,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++; } @@ -153,7 +154,7 @@ 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; diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index 54c8a2eb8..5a6b71fba 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -156,10 +156,13 @@ 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; @@ -284,9 +287,11 @@ 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; @@ -297,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)]) @@ -312,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 @@ -327,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; @@ -408,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; @@ -429,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; diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 607dc168f..6fbc170cb 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -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_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_id; api_nh->gate = rinfo->nh.gate; api_nh->type = NEXTHOP_TYPE_IPV4; if (cmd == ZEBRA_ROUTE_ADD) @@ -105,24 +106,26 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd) } /* 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,59 +139,59 @@ 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_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_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 vrf_bitmap_check(zclient->redist[AFI_IP][type], rip->vrf_id); } -void rip_redistribute_clean(void) +void rip_redistribute_clean(struct rip *rip) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], VRF_DEFAULT)) + if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], rip->vrf_id)) continue; if (zclient->sock > 0) zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, i, 0, - VRF_DEFAULT); + rip->vrf_id); - vrf_bitmap_unset(zclient->redist[AFI_IP][i], VRF_DEFAULT); + vrf_bitmap_unset(zclient->redist[AFI_IP][i], rip->vrf_id); } } -void rip_show_redistribute_config(struct vty *vty) +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->vrf_id)) continue; vty_out(vty, " %s", zebra_route_string(i)); diff --git a/ripd/ripd.c b/ripd/ripd.c index a6cfd9b15..6b9c5fe88 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -50,9 +50,6 @@ /* UDP receive buffer size */ #define RIP_UDP_RCV_BUF 41600 -/* RIP Structure. */ -struct rip *rip = NULL; - /* Prototypes. */ static void rip_output_process(struct connected *, struct sockaddr_in *, int, uint8_t); @@ -107,6 +104,11 @@ void rip_info_free(struct rip_info *rinfo) XFREE(MTYPE_RIP_INFO, rinfo); } +struct rip *rip_info_get_instance(const struct rip_info *rinfo) +{ + return route_table_get_info(rinfo->rp->table); +} + /* RIP route garbage collect timer. */ static int rip_garbage_collect(struct thread *t) { @@ -135,13 +137,13 @@ static int rip_garbage_collect(struct thread *t) return 0; } -static void rip_timeout_update(struct rip_info *rinfo); +static void rip_timeout_update(struct rip *rip, struct rip_info *rinfo); /* Add new route to the ECMP list. * RETURN: the new entry added in the list, or NULL if it is not the first * entry and ECMP is not allowed. */ -struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) +struct rip_info *rip_ecmp_add(struct rip *rip, struct rip_info *rinfo_new) { struct route_node *rp = rinfo_new->rp; struct rip_info *rinfo = NULL; @@ -161,8 +163,8 @@ struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) listnode_add(list, rinfo); if (rip_route_rte(rinfo)) { - rip_timeout_update(rinfo); - rip_zebra_ipv4_add(rp); + rip_timeout_update(rip, rinfo); + rip_zebra_ipv4_add(rip, rp); } /* Set the route change flag on the first entry. */ @@ -170,7 +172,7 @@ struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); /* Signal the output process to trigger an update (see section 2.5). */ - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); return rinfo; } @@ -178,7 +180,7 @@ struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) /* Replace the ECMP list with the new route. * RETURN: the new entry added in the list */ -struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) +struct rip_info *rip_ecmp_replace(struct rip *rip, struct rip_info *rinfo_new) { struct route_node *rp = rinfo_new->rp; struct list *list = (struct list *)rp->info; @@ -186,7 +188,7 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) struct listnode *node = NULL, *nextnode = NULL; if (list == NULL || listcount(list) == 0) - return rip_ecmp_add(rinfo_new); + return rip_ecmp_add(rip, rinfo_new); /* Get the first entry */ rinfo = listgetdata(listhead(list)); @@ -194,7 +196,7 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) /* Learnt route replaced by a local one. Delete it from zebra. */ if (rip_route_rte(rinfo) && !rip_route_rte(rinfo_new)) if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete(rp); + rip_zebra_ipv4_delete(rip, rp); /* Re-use the first entry, and delete the others. */ for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) @@ -210,16 +212,16 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) memcpy(rinfo, rinfo_new, sizeof(struct rip_info)); if (rip_route_rte(rinfo)) { - rip_timeout_update(rinfo); + rip_timeout_update(rip, rinfo); /* The ADD message implies an update. */ - rip_zebra_ipv4_add(rp); + rip_zebra_ipv4_add(rip, rp); } /* Set the route change flag. */ SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); /* Signal the output process to trigger an update (see section 2.5). */ - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); return rinfo; } @@ -230,7 +232,7 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) * the entry - the entry is the last one in the list; its metric is set * to INFINITY, and the garbage collector is started for it */ -struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) +struct rip_info *rip_ecmp_delete(struct rip *rip, struct rip_info *rinfo) { struct route_node *rp = rinfo->rp; struct list *list = (struct list *)rp->info; @@ -245,7 +247,7 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) if (rip_route_rte(rinfo) && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) /* The ADD message implies the update. */ - rip_zebra_ipv4_add(rp); + rip_zebra_ipv4_add(rip, rp); rip_info_free(rinfo); rinfo = NULL; } else { @@ -261,7 +263,7 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) if (rip_route_rte(rinfo) && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete(rp); + rip_zebra_ipv4_delete(rip, rp); } /* Set the route change flag on the first entry. */ @@ -269,7 +271,7 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); /* Signal the output process to trigger an update (see section 2.5). */ - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); return rinfo; } @@ -277,15 +279,20 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) /* Timeout RIP routes. */ static int rip_timeout(struct thread *t) { - rip_ecmp_delete((struct rip_info *)THREAD_ARG(t)); + struct rip_info *rinfo = THREAD_ARG(t); + struct rip *rip = rip_info_get_instance(rinfo); + + rip_ecmp_delete(rip, rinfo); + return 0; } -static void rip_timeout_update(struct rip_info *rinfo) +static void rip_timeout_update(struct rip *rip, struct rip_info *rinfo) { if (rinfo->metric != RIP_METRIC_INFINITY) { RIP_TIMER_OFF(rinfo->t_timeout); - RIP_TIMER_ON(rinfo->t_timeout, rip_timeout, rip->timeout_time); + thread_add_timer(master, rip_timeout, rinfo, rip->timeout_time, + &rinfo->t_timeout); } } @@ -324,7 +331,7 @@ static int rip_filter(int rip_distribute, struct prefix_ipv4 *p, } /* All interface filter check. */ - dist = distribute_lookup(rip->distribute_ctx, NULL); + dist = distribute_lookup(ri->rip->distribute_ctx, NULL); if (dist) { if (dist->list[distribute]) { alist = access_list_lookup(AFI_IP, @@ -363,9 +370,9 @@ static int rip_filter(int rip_distribute, struct prefix_ipv4 *p, } /* Check nexthop address validity. */ -static int rip_nexthop_check(struct in_addr *addr) +static int rip_nexthop_check(struct rip *rip, struct in_addr *addr) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; struct listnode *cnode; struct connected *ifc; @@ -390,6 +397,7 @@ static int rip_nexthop_check(struct in_addr *addr) static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, struct interface *ifp) { + struct rip *rip; int ret; struct prefix_ipv4 p; struct route_node *rp; @@ -410,9 +418,10 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, /* Make sure mask is applied. */ apply_mask_ipv4(&p); - /* Apply input filters. */ ri = ifp->info; + rip = ri->rip; + /* Apply input filters. */ ret = rip_filter(RIP_FILTER_IN, &p, ri); if (ret < 0) return; @@ -471,7 +480,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, nexthop = &rte->nexthop; /* Check if nexthop address is myself, then do nothing. */ - if (rip_nexthop_check(nexthop) < 0) { + if (rip_nexthop_check(rip, nexthop) < 0) { if (IS_RIP_DEBUG_PACKET) zlog_debug("Nexthop address %s is myself", inet_ntoa(*nexthop)); @@ -486,7 +495,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, newinfo.nh.type = NEXTHOP_TYPE_IPV4; newinfo.metric = rte->metric; newinfo.tag = ntohs(rte->tag); - newinfo.distance = rip_distance_apply(&newinfo); + newinfo.distance = rip_distance_apply(rip, &newinfo); new_dist = newinfo.distance ? newinfo.distance : ZEBRA_RIP_DISTANCE_DEFAULT; @@ -570,7 +579,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, mark it as a ghost */ if (new_dist <= old_dist && rte->metric != RIP_METRIC_INFINITY) - rip_ecmp_replace(&newinfo); + rip_ecmp_replace(rip, &newinfo); route_unlock_node(rp); return; @@ -587,7 +596,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, infinity (there is no point in adding a route which unusable). */ if (rte->metric != RIP_METRIC_INFINITY) - rip_ecmp_add(&newinfo); + rip_ecmp_add(rip, &newinfo); } else { /* Route is there but we are not sure the route is RIP or not. */ @@ -616,18 +625,18 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, || ((old_dist != new_dist) && same)) { if (listcount(list) == 1) { if (newinfo.metric != RIP_METRIC_INFINITY) - rip_ecmp_replace(&newinfo); + rip_ecmp_replace(rip, &newinfo); else - rip_ecmp_delete(rinfo); + rip_ecmp_delete(rip, rinfo); } else { if (newinfo.metric < rinfo->metric) - rip_ecmp_replace(&newinfo); + rip_ecmp_replace(rip, &newinfo); else if (newinfo.metric > rinfo->metric) - rip_ecmp_delete(rinfo); + rip_ecmp_delete(rip, rinfo); else if (new_dist < old_dist) - rip_ecmp_replace(&newinfo); + rip_ecmp_replace(rip, &newinfo); else if (new_dist > old_dist) - rip_ecmp_delete(rinfo); + rip_ecmp_delete(rip, rinfo); else { int update = CHECK_FLAG(rinfo->flags, RIP_RTF_FIB) @@ -641,20 +650,20 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, RIP_TIMER_OFF(rinfo->t_garbage_collect); memcpy(rinfo, &newinfo, sizeof(struct rip_info)); - rip_timeout_update(rinfo); + rip_timeout_update(rip, rinfo); if (update) - rip_zebra_ipv4_add(rp); + rip_zebra_ipv4_add(rip, rp); /* - Set the route change flag on the * first entry. */ rinfo = listgetdata(listhead(list)); SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } } } else /* same & no change */ - rip_timeout_update(rinfo); + rip_timeout_update(rip, rinfo); /* Unlock tempolary lock of the route. */ route_unlock_node(rp); @@ -1080,6 +1089,8 @@ static void rip_response_process(struct rip_packet *packet, int size, struct sockaddr_in *from, struct connected *ifc) { + struct rip_interface *ri = ifc->ifp->info; + struct rip *rip = ri->rip; caddr_t lim; struct rte *rte; struct prefix_ipv4 ifaddr; @@ -1095,7 +1106,7 @@ static void rip_response_process(struct rip_packet *packet, int size, if (from->sin_port != htons(RIP_PORT_DEFAULT)) { zlog_info("response doesn't come from RIP port: %d", from->sin_port); - rip_peer_bad_packet(from); + rip_peer_bad_packet(rip, from); return; } @@ -1103,12 +1114,12 @@ static void rip_response_process(struct rip_packet *packet, int size, whether the datagram is from a valid neighbor; the source of the datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */ - if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT) + if (if_lookup_address((void *)&from->sin_addr, AF_INET, rip->vrf_id) == NULL) { zlog_info( "This datagram doesn't came from a valid neighbor: %s", inet_ntoa(from->sin_addr)); - rip_peer_bad_packet(from); + rip_peer_bad_packet(rip, from); return; } @@ -1118,7 +1129,7 @@ static void rip_response_process(struct rip_packet *packet, int size, ; /* Alredy done in rip_read () */ /* Update RIP peer. */ - rip_peer_update(from, packet->version); + rip_peer_update(rip, from, packet->version); /* Set RTE pointer. */ rte = packet->rte; @@ -1147,7 +1158,7 @@ static void rip_response_process(struct rip_packet *packet, int size, if (!rip_destination_check(rte->prefix)) { zlog_info( "Network is net 0 or net 127 or it is not unicast network"); - rip_peer_bad_route(from); + rip_peer_bad_route(rip, from); continue; } @@ -1157,7 +1168,7 @@ static void rip_response_process(struct rip_packet *packet, int size, /* - is the metric valid (i.e., between 1 and 16, inclusive) */ if (!(rte->metric >= 1 && rte->metric <= 16)) { zlog_info("Route's metric is not in the 1-16 range."); - rip_peer_bad_route(from); + rip_peer_bad_route(rip, from); continue; } @@ -1165,7 +1176,7 @@ static void rip_response_process(struct rip_packet *packet, int size, if (packet->version == RIPv1 && rte->nexthop.s_addr != 0) { zlog_info("RIPv1 packet with nexthop value %s", inet_ntoa(rte->nexthop)); - rip_peer_bad_route(from); + rip_peer_bad_route(rip, from); continue; } @@ -1186,7 +1197,7 @@ static void rip_response_process(struct rip_packet *packet, int size, } if (!if_lookup_address((void *)&rte->nexthop, AF_INET, - VRF_DEFAULT)) { + rip->vrf_id)) { struct route_node *rn; struct rip_info *rinfo; @@ -1297,7 +1308,7 @@ static void rip_response_process(struct rip_packet *packet, int size, zlog_warn( "RIPv2 address %s is not mask /%d applied one", inet_ntoa(rte->prefix), ip_masklen(rte->mask)); - rip_peer_bad_route(from); + rip_peer_bad_route(rip, from); continue; } @@ -1371,10 +1382,14 @@ int rip_create_socket(void) static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to, struct connected *ifc) { + struct rip_interface *ri; + struct rip *rip; int ret; struct sockaddr_in sin; assert(ifc != NULL); + ri = ifc->ifp->info; + rip = ri->rip; if (IS_RIP_DEBUG_PACKET) { #define ADDRESS_SIZE 20 @@ -1447,9 +1462,10 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to, } /* Add redistributed route to RIP table. */ -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) +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) { int ret; struct route_node *rp = NULL; @@ -1496,22 +1512,22 @@ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, } } - (void)rip_ecmp_replace(&newinfo); + (void)rip_ecmp_replace(rip, &newinfo); route_unlock_node(rp); } else - (void)rip_ecmp_add(&newinfo); + (void)rip_ecmp_add(rip, &newinfo); if (IS_RIP_DEBUG_EVENT) { zlog_debug("Redistribute new prefix %s/%d", inet_ntoa(p->prefix), p->prefixlen); } - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } /* Delete redistributed route from RIP table. */ -void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, - ifindex_t ifindex) +void rip_redistribute_delete(struct rip *rip, int type, int sub_type, + struct prefix_ipv4 *p, ifindex_t ifindex) { int ret; struct route_node *rp; @@ -1545,9 +1561,9 @@ void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, inet_ntoa(p->prefix), p->prefixlen, ifindex2ifname(ifindex, - VRF_DEFAULT)); + rip->vrf_id)); - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } } route_unlock_node(rp); @@ -1558,6 +1574,7 @@ void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, static void rip_request_process(struct rip_packet *packet, int size, struct sockaddr_in *from, struct connected *ifc) { + struct rip *rip; caddr_t lim; struct rte *rte; struct prefix_ipv4 p; @@ -1573,13 +1590,14 @@ static void rip_request_process(struct rip_packet *packet, int size, ri = ifc->ifp->info; if (!ri->running) return; + rip = ri->rip; /* When passive interface is specified, suppress responses */ if (ri->passive) return; /* RIP peer update. */ - rip_peer_update(from, packet->version); + rip_peer_update(rip, from, packet->version); lim = ((caddr_t)packet) + size; rte = packet->rte; @@ -1635,6 +1653,7 @@ static void rip_request_process(struct rip_packet *packet, int size, /* First entry point of RIP packet. */ static int rip_read(struct thread *t) { + struct rip *rip = THREAD_ARG(t); int sock; int ret; int rtenum; @@ -1654,7 +1673,7 @@ static int rip_read(struct thread *t) rip->t_read = NULL; /* Add myself to tne next event */ - rip_event(RIP_READ, sock); + rip_event(rip, RIP_READ, sock); /* RIPd manages only IPv4. */ memset(&from, 0, sizeof(struct sockaddr_in)); @@ -1668,14 +1687,14 @@ static int rip_read(struct thread *t) } /* Check is this packet comming from myself? */ - if (if_check_address(from.sin_addr)) { + if (if_check_address(rip, from.sin_addr)) { if (IS_RIP_DEBUG_PACKET) zlog_debug("ignore packet comes from myself"); return -1; } /* Which interface is this packet comes from. */ - ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, VRF_DEFAULT); + ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, rip->vrf_id); if (ifc) ifp = ifc->ifp; @@ -1712,13 +1731,13 @@ static int rip_read(struct thread *t) if (len < RIP_PACKET_MINSIZ) { zlog_warn("packet size %d is smaller than minimum size %d", len, RIP_PACKET_MINSIZ); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return len; } if (len > RIP_PACKET_MAXSIZ) { zlog_warn("packet size %d is larger than max size %d", len, RIP_PACKET_MAXSIZ); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return len; } @@ -1726,7 +1745,7 @@ static int rip_read(struct thread *t) if ((len - RIP_PACKET_MINSIZ) % 20) { zlog_warn("packet size %d is wrong for RIP packet alignment", len); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return len; } @@ -1740,7 +1759,7 @@ static int rip_read(struct thread *t) if (packet->version == 0) { zlog_info("version 0 with command %d received.", packet->command); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1757,11 +1776,11 @@ static int rip_read(struct thread *t) /* Is RIP running or is this RIP neighbor ?*/ ri = ifp->info; - if (!ri->running && !rip_neighbor_lookup(&from)) { + if (!ri->running && !rip_neighbor_lookup(rip, &from)) { if (IS_RIP_DEBUG_EVENT) zlog_debug("RIP is not enabled on interface %s.", ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1775,7 +1794,7 @@ static int rip_read(struct thread *t) zlog_debug( " packet's v%d doesn't fit to if version spec", packet->version); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1790,7 +1809,7 @@ static int rip_read(struct thread *t) "packet RIPv%d is dropped because authentication disabled", packet->version); ripd_notif_send_auth_type_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1827,7 +1846,7 @@ static int rip_read(struct thread *t) "RIPv1" " dropped because authentication enabled"); ripd_notif_send_auth_type_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } } else if (ri->auth_type != RIP_NO_AUTH) { @@ -1840,7 +1859,7 @@ static int rip_read(struct thread *t) zlog_debug( "RIPv2 authentication failed: no auth RTE in packet"); ripd_notif_send_auth_type_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1851,7 +1870,7 @@ static int rip_read(struct thread *t) "RIPv2" " dropped because authentication enabled"); ripd_notif_send_auth_type_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1887,7 +1906,7 @@ static int rip_read(struct thread *t) zlog_debug("RIPv2 %s authentication failure", auth_desc); ripd_notif_send_auth_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } } @@ -1906,16 +1925,16 @@ static int rip_read(struct thread *t) zlog_info( "Obsolete command %s received, please sent it to routed", lookup_msg(rip_msg, packet->command, NULL)); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); break; case RIP_POLL_ENTRY: zlog_info("Obsolete command %s received", lookup_msg(rip_msg, packet->command, NULL)); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); break; default: zlog_info("Unknown RIP command %d received", packet->command); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); break; } @@ -1955,6 +1974,7 @@ static int rip_write_rte(int num, struct stream *s, struct prefix_ipv4 *p, void rip_output_process(struct connected *ifc, struct sockaddr_in *to, int route_type, uint8_t version) { + struct rip *rip; int ret; struct stream *s; struct route_node *rp; @@ -1984,6 +2004,10 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, ifc->ifp->name, ifc->ifp->ifindex); } + /* Get RIP interface. */ + ri = ifc->ifp->info; + rip = ri->rip; + /* Set output stream. */ s = rip->obuf; @@ -1991,9 +2015,6 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, stream_reset(s); rtemax = RIP_MAX_RTE; - /* Get RIP interface. */ - ri = ifc->ifp->info; - /* If output interface is in simple password authentication mode, we need space for authentication data. */ if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) @@ -2366,9 +2387,9 @@ static void rip_update_interface(struct connected *ifc, uint8_t version, } /* Update send to all interface and neighbor. */ -static void rip_update_process(int route_type) +static void rip_update_process(struct rip *rip, int route_type) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct listnode *ifnode, *ifnnode; struct connected *connected; struct interface *ifp; @@ -2431,7 +2452,7 @@ static void rip_update_process(int route_type) p = &rp->p; connected = if_lookup_address(&p->u.prefix4, AF_INET, - VRF_DEFAULT); + rip->vrf_id); if (!connected) { zlog_warn( "Neighbor %s doesn't have connected interface!", @@ -2453,6 +2474,8 @@ static void rip_update_process(int route_type) /* RIP's periodical timer. */ static int rip_update(struct thread *t) { + struct rip *rip = THREAD_ARG(t); + /* Clear timer pointer. */ rip->t_update = NULL; @@ -2460,7 +2483,7 @@ static int rip_update(struct thread *t) zlog_debug("update timer fire!"); /* Process update output. */ - rip_update_process(rip_all_route); + rip_update_process(rip, rip_all_route); /* Triggered updates may be suppressed if a regular update is due by the time the triggered update would be sent. */ @@ -2468,13 +2491,13 @@ static int rip_update(struct thread *t) rip->trigger = 0; /* Register myself. */ - rip_event(RIP_UPDATE_EVENT, 0); + rip_event(rip, RIP_UPDATE_EVENT, 0); return 0; } /* Walk down the RIP routing table then clear changed flag. */ -static void rip_clear_changed_flag(void) +static void rip_clear_changed_flag(struct rip *rip) { struct route_node *rp; struct rip_info *rinfo = NULL; @@ -2494,7 +2517,7 @@ static void rip_clear_changed_flag(void) /* Triggered update interval timer. */ static int rip_triggered_interval(struct thread *t) { - int rip_triggered_update(struct thread *); + struct rip *rip = THREAD_ARG(t); rip->t_triggered_interval = NULL; @@ -2508,6 +2531,7 @@ static int rip_triggered_interval(struct thread *t) /* Execute triggered update. */ static int rip_triggered_update(struct thread *t) { + struct rip *rip = THREAD_ARG(t); int interval; /* Clear thred pointer. */ @@ -2523,11 +2547,11 @@ static int rip_triggered_update(struct thread *t) /* Split Horizon processing is done when generating triggered updates as well as normal updates (see section 2.6). */ - rip_update_process(rip_changed_route); + rip_update_process(rip, rip_changed_route); /* Once all of the triggered updates have been generated, the route change flags should be cleared. */ - rip_clear_changed_flag(); + rip_clear_changed_flag(rip); /* After a triggered update is sent, a timer should be set for a random interval between 1 and 5 seconds. If other changes that @@ -2536,14 +2560,14 @@ static int rip_triggered_update(struct thread *t) interval = (random() % 5) + 1; rip->t_triggered_interval = NULL; - thread_add_timer(master, rip_triggered_interval, NULL, interval, + thread_add_timer(master, rip_triggered_interval, rip, interval, &rip->t_triggered_interval); return 0; } /* Withdraw redistributed route. */ -void rip_redistribute_withdraw(int type) +void rip_redistribute_withdraw(struct rip *rip, int type) { struct route_node *rp; struct rip_info *rinfo = NULL; @@ -2572,17 +2596,31 @@ void rip_redistribute_withdraw(int type) p->prefixlen, ifindex2ifname( rinfo->nh.ifindex, - VRF_DEFAULT)); + rip->vrf_id)); } - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } } } +struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id) +{ + struct vrf *vrf; + + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) + return NULL; + + return vrf->info; +} + /* Create new RIP instance and set it to global variable. */ -int rip_create(int socket) +struct rip *rip_create(struct vrf *vrf, int socket) { + struct rip *rip; + struct interface *ifp; + rip = XCALLOC(MTYPE_RIP, sizeof(struct rip)); /* Set initial value. */ @@ -2606,6 +2644,7 @@ int rip_create(int socket) /* Initialize RIP data structures. */ rip->table = route_table_init(); + route_table_set_info(rip->table, rip); rip->neighbor = route_table_init(); rip->peer_list = list_new(); rip->peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp; @@ -2632,10 +2671,20 @@ int rip_create(int socket) rip->sock = socket; /* Create read and timer thread. */ - rip_event(RIP_READ, rip->sock); - rip_event(RIP_UPDATE_EVENT, 1); + rip_event(rip, RIP_READ, rip->sock); + rip_event(rip, RIP_UPDATE_EVENT, 1); - return 0; + /* Link RIP instance to VRF. */ + rip->vrf_id = vrf->vrf_id; + vrf->info = rip; + FOR_ALL_INTERFACES (vrf, ifp) { + struct rip_interface *ri; + + ri = ifp->info; + ri->rip = rip; + } + + return rip; } /* Sned RIP request to the destination. */ @@ -2704,19 +2753,19 @@ static int rip_update_jitter(unsigned long time) return jitter / JITTER_BOUND; } -void rip_event(enum rip_event event, int sock) +void rip_event(struct rip *rip, enum rip_event event, int sock) { int jitter = 0; switch (event) { case RIP_READ: rip->t_read = NULL; - thread_add_read(master, rip_read, NULL, sock, &rip->t_read); + thread_add_read(master, rip_read, rip, sock, &rip->t_read); break; case RIP_UPDATE_EVENT: RIP_TIMER_OFF(rip->t_update); jitter = rip_update_jitter(rip->update_time); - thread_add_timer(master, rip_update, NULL, + thread_add_timer(master, rip_update, rip, sock ? 2 : rip->update_time + jitter, &rip->t_update); break; @@ -2724,7 +2773,7 @@ void rip_event(enum rip_event event, int sock) if (rip->t_triggered_interval) rip->trigger = 1; else - thread_add_event(master, rip_triggered_update, NULL, 0, + thread_add_event(master, rip_triggered_update, rip, 0, &rip->t_triggered_update); break; default: @@ -2772,16 +2821,13 @@ static void rip_distance_table_node_cleanup(struct route_table *table, } /* Apply RIP information to distance method. */ -uint8_t rip_distance_apply(struct rip_info *rinfo) +uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo) { struct route_node *rn; struct prefix_ipv4 p; struct rip_distance *rdistance; struct access_list *alist; - if (!rip) - return 0; - memset(&p, 0, sizeof(struct prefix_ipv4)); p.family = AF_INET; p.prefix = rinfo->from; @@ -2813,7 +2859,7 @@ uint8_t rip_distance_apply(struct rip_info *rinfo) return 0; } -static void rip_distance_show(struct vty *vty) +static void rip_distance_show(struct vty *vty, struct rip *rip) { struct route_node *rn; struct rip_distance *rdistance; @@ -2840,16 +2886,13 @@ static void rip_distance_show(struct vty *vty) } /* Update ECMP routes to zebra when ECMP is disabled. */ -void rip_ecmp_disable(void) +void rip_ecmp_disable(struct rip *rip) { struct route_node *rp; struct rip_info *rinfo, *tmp_rinfo; struct list *list; struct listnode *node, *nextnode; - if (!rip) - return; - for (rp = route_top(rip->table); rp; rp = route_next(rp)) if ((list = rp->info) != NULL && listcount(list) > 1) { rinfo = listgetdata(listhead(list)); @@ -2867,13 +2910,13 @@ void rip_ecmp_disable(void) } /* Update zebra. */ - rip_zebra_ipv4_add(rp); + rip_zebra_ipv4_add(rip, rp); /* Set the route change flag. */ SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); /* Signal the output process to trigger an update. */ - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } } @@ -2924,11 +2967,13 @@ DEFUN (show_ip_rip, IP_STR "Show RIP routes\n") { + struct rip *rip; struct route_node *np; struct rip_info *rinfo = NULL; struct list *list = NULL; struct listnode *listnode = NULL; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (!rip) return CMD_SUCCESS; @@ -3028,13 +3073,15 @@ DEFUN (show_ip_rip_status, "Show RIP routes\n" "IP routing protocol process parameters and statistics\n") { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct rip *rip; + struct vrf *vrf; struct interface *ifp; struct rip_interface *ri; extern const struct message ri_version_msg[]; const char *send_version; const char *receive_version; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (!rip) return CMD_SUCCESS; @@ -3055,7 +3102,7 @@ DEFUN (show_ip_rip_status, /* Redistribute information. */ vty_out(vty, " Redistributing:"); - rip_show_redistribute_config(vty); + rip_show_redistribute_config(vty, rip); vty_out(vty, "\n"); vty_out(vty, " Default version control: send version %s,", @@ -3068,6 +3115,7 @@ DEFUN (show_ip_rip_status, vty_out(vty, " Interface Send Recv Key-chain\n"); + vrf = vrf_lookup_by_id(rip->vrf_id); FOR_ALL_INTERFACES (vrf, ifp) { ri = ifp->info; @@ -3098,7 +3146,7 @@ DEFUN (show_ip_rip_status, } vty_out(vty, " Routing for Networks:\n"); - rip_show_network_config(vty); + rip_show_network_config(vty, rip); { int found_passive = 0; @@ -3120,9 +3168,9 @@ DEFUN (show_ip_rip_status, vty_out(vty, " Routing Information Sources:\n"); vty_out(vty, " Gateway BadPackets BadRoutes Distance Last Update\n"); - rip_peer_display(vty); + rip_peer_display(vty, rip); - rip_distance_show(vty); + rip_distance_show(vty, rip); return CMD_SUCCESS; } @@ -3136,16 +3184,21 @@ static int config_write_rip(struct vty *vty) dnode = yang_dnode_get(running_config->dnode, "/frr-ripd:ripd/instance"); if (dnode) { + struct rip *rip; + write++; nb_cli_show_dnode_cmds(vty, dnode, false); - /* Distribute configuration. */ - write += config_write_distribute(vty, - rip->distribute_ctx); + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); + if (rip) { + /* Distribute configuration. */ + write += config_write_distribute(vty, + rip->distribute_ctx); - /* Interface routemap configuration */ - write += config_write_if_rmap(vty); + /* Interface routemap configuration */ + write += config_write_if_rmap(vty); + } } return write; } @@ -3214,6 +3267,8 @@ static void rip_distribute_update(struct distribute_ctx *ctx, void rip_distribute_update_interface(struct interface *ifp) { + struct rip_interface *ri = ifp->info; + struct rip *rip = ri->rip; struct distribute *dist; if (!rip) @@ -3240,8 +3295,10 @@ static void rip_distribute_update_all_wrapper(struct access_list *notused) } /* Delete all added rip route. */ -void rip_clean(void) +void rip_clean(struct rip *rip) { + struct vrf *vrf; + struct interface *ifp; struct route_node *rp; /* Clear RIP routes */ @@ -3255,7 +3312,7 @@ void rip_clean(void) rinfo = listgetdata(listhead(list)); if (rip_route_rte(rinfo)) - rip_zebra_ipv4_delete(rp); + rip_zebra_ipv4_delete(rip, rp); for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { RIP_TIMER_OFF(rinfo->t_timeout); @@ -3292,15 +3349,25 @@ void rip_clean(void) list_delete(&rip->peer_list); distribute_list_delete(&rip->distribute_ctx); - rip_clean_network(); - rip_passive_nondefault_clean(); + rip_clean_network(rip); + rip_passive_nondefault_clean(rip); vector_free(rip->enable_interface); route_table_finish(rip->enable_network); vector_free(rip->passive_nondefault); list_delete(&rip->offset_list_master); - rip_interfaces_clean(); + rip_interfaces_clean(rip); route_table_finish(rip->distance_table); - rip_redistribute_clean(); + rip_redistribute_clean(rip); + + vrf = vrf_lookup_by_id(rip->vrf_id); + vrf->info = NULL; + + FOR_ALL_INTERFACES (vrf, ifp) { + struct rip_interface *ri; + + ri = ifp->info; + ri->rip = NULL; + } XFREE(MTYPE_RIP, rip); } @@ -3344,17 +3411,12 @@ void rip_if_rmap_update_interface(struct interface *ifp) rip_if_rmap_update(if_rmap); } -static void rip_routemap_update_redistribute(void) +static void rip_routemap_update_redistribute(struct rip *rip) { - int i; - - if (rip) { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (rip->route_map[i].name) - rip->route_map[i].map = - route_map_lookup_by_name( - rip->route_map[i].name); - } + for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (rip->route_map[i].name) + rip->route_map[i].map = route_map_lookup_by_name( + rip->route_map[i].name); } } @@ -3362,12 +3424,15 @@ static void rip_routemap_update_redistribute(void) static void rip_routemap_update(const char *notused) { struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct rip *rip; struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) rip_if_rmap_update_interface(ifp); - rip_routemap_update_redistribute(); + rip = vrf->info; + if (rip) + rip_routemap_update_redistribute(rip); } /* Allocate new rip structure and set default value. */ diff --git a/ripd/ripd.h b/ripd/ripd.h index af0d3021a..a18a74157 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -99,6 +99,9 @@ /* RIP structure. */ struct rip { + /* VRF ID. */ + vrf_id_t vrf_id; + /* RIP socket. */ int sock; @@ -256,6 +259,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; @@ -313,6 +319,9 @@ struct rip_interface { /* RIP peer information. */ struct rip_peer { + /* Parent routing instance. */ + struct rip *rip; + /* Peer address. */ struct in_addr addr; @@ -385,6 +394,9 @@ enum rip_event { #define RIP_OFFSET_LIST_MAX 2 struct rip_offset_list { + /* Parent routing instance. */ + struct rip *rip; + char *ifname; struct { @@ -396,75 +408,86 @@ 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_route_map_init(void); 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_create(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_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 *); -extern int rip_show_network_config(struct vty *); -extern void rip_show_redistribute_config(struct vty *); - -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_clean(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_offset_list *rip_offset_list_new(const char *ifname); +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(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 *, @@ -476,9 +499,6 @@ extern int offset_list_cmp(struct rip_offset_list *o1, 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; /* Master thread strucutre. */ |