diff options
| author | Renato Westphal <renato@opensourcerouting.org> | 2021-10-14 12:12:37 -0300 | 
|---|---|---|
| committer | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2023-04-19 09:15:01 -0300 | 
| commit | c262df828b2475632f590c256db677b424d868c7 (patch) | |
| tree | 85a8ab1e5ff016e9cdc28e18f91d263a207c8d32 /ripd/rip_peer.c | |
| parent | fec51f2e2be021108dc1de4dd1ea89516082eaf7 (diff) | |
ripd: support BFD integration
Implement RIP peer monitoring with BFD.
RFC 5882 Generic Application of Bidirectional Forwarding Detection
(BFD), Section 10.3 Interactions with RIP.
Co-authored-by: Renato Westphal <renato@opensourcerouting.org>
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
Diffstat (limited to 'ripd/rip_peer.c')
| -rw-r--r-- | ripd/rip_peer.c | 68 | 
1 files changed, 60 insertions, 8 deletions
diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index 9410ef380e..449abe47b8 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -11,8 +11,10 @@  #include "linklist.h"  #include "frrevent.h"  #include "memory.h" +#include "table.h"  #include "ripd/ripd.h" +#include "ripd/rip_bfd.h"  DEFINE_MTYPE_STATIC(RIPD, RIP_PEER, "RIP peer"); @@ -21,8 +23,9 @@ static struct rip_peer *rip_peer_new(void)  	return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer));  } -static void rip_peer_free(struct rip_peer *peer) +void rip_peer_free(struct rip_peer *peer)  { +	bfd_sess_free(&peer->bfd_session);  	EVENT_OFF(peer->t_timeout);  	XFREE(MTYPE_RIP_PEER, peer);  } @@ -62,7 +65,8 @@ static void rip_peer_timeout(struct event *t)  }  /* Get RIP peer.  At the same time update timeout thread. */ -static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr) +static struct rip_peer *rip_peer_get(struct rip *rip, struct rip_interface *ri, +				     struct in_addr *addr)  {  	struct rip_peer *peer; @@ -73,7 +77,9 @@ static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr)  	} else {  		peer = rip_peer_new();  		peer->rip = rip; +		peer->ri = ri;  		peer->addr = *addr; +		rip_bfd_session_update(peer);  		listnode_add_sort(rip->peer_list, peer);  	} @@ -87,24 +93,27 @@ static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr)  	return peer;  } -void rip_peer_update(struct rip *rip, struct sockaddr_in *from, uint8_t version) +void rip_peer_update(struct rip *rip, struct rip_interface *ri, +		     struct sockaddr_in *from, uint8_t version)  {  	struct rip_peer *peer; -	peer = rip_peer_get(rip, &from->sin_addr); +	peer = rip_peer_get(rip, ri, &from->sin_addr);  	peer->version = version;  } -void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from) +void rip_peer_bad_route(struct rip *rip, struct rip_interface *ri, +			struct sockaddr_in *from)  {  	struct rip_peer *peer; -	peer = rip_peer_get(rip, &from->sin_addr); +	peer = rip_peer_get(rip, ri, &from->sin_addr);  	peer->recv_badroutes++;  } -void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from) +void rip_peer_bad_packet(struct rip *rip, struct rip_interface *ri, +			 struct sockaddr_in *from)  {  	struct rip_peer *peer; -	peer = rip_peer_get(rip, &from->sin_addr); +	peer = rip_peer_get(rip, ri, &from->sin_addr);  	peer->recv_badpackets++;  } @@ -155,3 +164,46 @@ void rip_peer_list_del(void *arg)  {  	rip_peer_free(arg);  } + +void rip_peer_delete_routes(const struct rip_peer *peer) +{ +	struct route_node *route_node; + +	for (route_node = route_top(peer->rip->table); route_node; +	     route_node = route_next(route_node)) { +		struct rip_info *route_entry; +		struct listnode *listnode; +		struct listnode *listnode_next; +		struct list *list; + +		list = route_node->info; +		if (list == NULL) +			continue; + +		for (ALL_LIST_ELEMENTS(list, listnode, listnode_next, +				       route_entry)) { +			if (!rip_route_rte(route_entry)) +				continue; +			if (route_entry->from.s_addr != peer->addr.s_addr) +				continue; + +			if (listcount(list) == 1) { +				EVENT_OFF(route_entry->t_timeout); +				EVENT_OFF(route_entry->t_garbage_collect); +				listnode_delete(list, route_entry); +				if (list_isempty(list)) { +					list_delete((struct list **)&route_node +							    ->info); +					route_unlock_node(route_node); +				} +				rip_info_free(route_entry); + +				/* Signal the output process to trigger an +				 * update (see section 2.5). */ +				rip_event(peer->rip, RIP_TRIGGERED_UPDATE, 0); +			} else +				rip_ecmp_delete(peer->rip, route_entry); +			break; +		} +	} +}  | 
