#include "eigrpd/eigrp_network.h"
#include "eigrpd/eigrp_topology.h"
#include "eigrpd/eigrp_memory.h"
+#include "eigrpd/eigrp_errors.h"
-struct eigrp_neighbor *
-eigrp_nbr_new (struct eigrp_interface *ei)
+struct eigrp_neighbor *eigrp_nbr_new(struct eigrp_interface *ei)
{
- struct eigrp_neighbor *nbr;
+ struct eigrp_neighbor *nbr;
- /* Allcate new neighbor. */
- nbr = XCALLOC (MTYPE_EIGRP_NEIGHBOR, sizeof (struct eigrp_neighbor));
+ /* Allcate new neighbor. */
+ nbr = XCALLOC(MTYPE_EIGRP_NEIGHBOR, sizeof(struct eigrp_neighbor));
- /* Relate neighbor to the interface. */
- nbr->ei = ei;
+ /* Relate neighbor to the interface. */
+ nbr->ei = ei;
- /* Set default values. */
- eigrp_nbr_state_set (nbr, EIGRP_NEIGHBOR_DOWN);
+ /* Set default values. */
+ eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
- return nbr;
+ return nbr;
}
/**
* @par
* Create a new neighbor structure and initalize it.
*/
-static struct eigrp_neighbor *
-eigrp_nbr_add (struct eigrp_interface *ei, struct eigrp_header *eigrph,
- struct ip *iph)
+static struct eigrp_neighbor *eigrp_nbr_add(struct eigrp_interface *ei,
+ struct eigrp_header *eigrph,
+ struct ip *iph)
{
- struct eigrp_neighbor *nbr;
+ struct eigrp_neighbor *nbr;
- nbr = eigrp_nbr_new (ei);
- nbr->src = iph->ip_src;
+ nbr = eigrp_nbr_new(ei);
+ nbr->src = iph->ip_src;
- // if (IS_DEBUG_EIGRP_EVENT)
- // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi),
- // inet_ntoa (nbr->router_id));
+ // if (IS_DEBUG_EIGRP_EVENT)
+ // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi),
+ // inet_ntoa (nbr->router_id));
- return nbr;
+ return nbr;
}
-struct eigrp_neighbor *
-eigrp_nbr_get (struct eigrp_interface *ei, struct eigrp_header *eigrph,
- struct ip *iph)
+struct eigrp_neighbor *eigrp_nbr_get(struct eigrp_interface *ei,
+ struct eigrp_header *eigrph,
+ struct ip *iph)
{
- struct eigrp_neighbor *nbr;
- struct listnode *node, *nnode;
+ struct eigrp_neighbor *nbr;
+ struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
- {
- if (iph->ip_src.s_addr == nbr->src.s_addr)
- {
- return nbr;
- }
- }
+ for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
+ if (iph->ip_src.s_addr == nbr->src.s_addr) {
+ return nbr;
+ }
+ }
- nbr = eigrp_nbr_add (ei, eigrph, iph);
- listnode_add (ei->nbrs, nbr);
+ nbr = eigrp_nbr_add(ei, eigrph, iph);
+ listnode_add(ei->nbrs, nbr);
- return nbr;
+ return nbr;
}
/**
* Function is used for neighbor lookup by address
* in specified interface.
*/
-struct eigrp_neighbor *
-eigrp_nbr_lookup_by_addr (struct eigrp_interface *ei, struct in_addr *addr)
+struct eigrp_neighbor *eigrp_nbr_lookup_by_addr(struct eigrp_interface *ei,
+ struct in_addr *addr)
{
- struct eigrp_neighbor *nbr;
- struct listnode *node, *nnode;
-
- for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
- {
- if (addr->s_addr == nbr->src.s_addr)
- {
- return nbr;
- }
- }
-
- return NULL;
+ struct eigrp_neighbor *nbr;
+ struct listnode *node, *nnode;
+
+ for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
+ if (addr->s_addr == nbr->src.s_addr) {
+ return nbr;
+ }
+ }
+
+ return NULL;
}
/**
* Function is used for neighbor lookup by address
* in whole EIGRP process.
*/
-struct eigrp_neighbor *
-eigrp_nbr_lookup_by_addr_process (struct eigrp *eigrp, struct in_addr nbr_addr)
+struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *eigrp,
+ struct in_addr nbr_addr)
{
- struct eigrp_interface *ei;
- struct listnode *node, *node2, *nnode2;
- struct eigrp_neighbor *nbr;
-
- /* iterate over all eigrp interfaces */
- for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
- {
- /* iterate over all neighbors on eigrp interface */
- for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr))
- {
- /* compare if neighbor address is same as arg address */
- if (nbr->src.s_addr == nbr_addr.s_addr)
- {
- return nbr;
- }
- }
- }
-
- return NULL;
+ struct eigrp_interface *ei;
+ struct listnode *node, *node2, *nnode2;
+ struct eigrp_neighbor *nbr;
+
+ /* iterate over all eigrp interfaces */
+ for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
+ /* iterate over all neighbors on eigrp interface */
+ for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
+ /* compare if neighbor address is same as arg address */
+ if (nbr->src.s_addr == nbr_addr.s_addr) {
+ return nbr;
+ }
+ }
+ }
+
+ return NULL;
}
/* Delete specified EIGRP neighbor from interface. */
-void
-eigrp_nbr_delete (struct eigrp_neighbor *nbr)
+void eigrp_nbr_delete(struct eigrp_neighbor *nbr)
{
- eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
- if (nbr->ei)
- eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr);
-
- /* Cancel all events. *//* Thread lookup cost would be negligible. */
- thread_cancel_event (master, nbr);
- eigrp_fifo_free (nbr->multicast_queue);
- eigrp_fifo_free (nbr->retrans_queue);
- THREAD_OFF (nbr->t_holddown);
-
- if (nbr->ei)
- listnode_delete (nbr->ei->nbrs,nbr);
- XFREE (MTYPE_EIGRP_NEIGHBOR, nbr);
+ eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
+ if (nbr->ei)
+ eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr);
+
+ /* Cancel all events. */ /* Thread lookup cost would be negligible. */
+ thread_cancel_event(master, nbr);
+ eigrp_fifo_free(nbr->multicast_queue);
+ eigrp_fifo_free(nbr->retrans_queue);
+ THREAD_OFF(nbr->t_holddown);
+
+ if (nbr->ei)
+ listnode_delete(nbr->ei->nbrs, nbr);
+ XFREE(MTYPE_EIGRP_NEIGHBOR, nbr);
}
-int
-holddown_timer_expired (struct thread *thread)
+int holddown_timer_expired(struct thread *thread)
{
- struct eigrp_neighbor *nbr;
+ struct eigrp_neighbor *nbr;
- nbr = THREAD_ARG (thread);
+ nbr = THREAD_ARG(thread);
- zlog_info ("Neighbor %s (%s) is down: holding time expired",
- inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
- nbr->state = EIGRP_NEIGHBOR_DOWN;
- eigrp_nbr_delete (nbr);
+ zlog_info("Neighbor %s (%s) is down: holding time expired",
+ inet_ntoa(nbr->src),
+ ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
+ nbr->state = EIGRP_NEIGHBOR_DOWN;
+ eigrp_nbr_delete(nbr);
- return 0;
+ return 0;
}
-u_char
-eigrp_nbr_state_get (struct eigrp_neighbor *nbr)
+uint8_t eigrp_nbr_state_get(struct eigrp_neighbor *nbr)
{
- return(nbr->state);
+ return (nbr->state);
}
-void
-eigrp_nbr_state_set (struct eigrp_neighbor *nbr, u_char state)
+void eigrp_nbr_state_set(struct eigrp_neighbor *nbr, uint8_t state)
{
- nbr->state = state;
-
- if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN)
- {
- // reset all the seq/ack counters
- nbr->recv_sequence_number = 0;
- nbr->init_sequence_number = 0;
- nbr->retrans_counter = 0;
-
- // Kvalues
- nbr->K1 = EIGRP_K1_DEFAULT;
- nbr->K2 = EIGRP_K2_DEFAULT;
- nbr->K3 = EIGRP_K3_DEFAULT;
- nbr->K4 = EIGRP_K4_DEFAULT;
- nbr->K5 = EIGRP_K5_DEFAULT;
- nbr->K6 = EIGRP_K6_DEFAULT;
-
- // hold time..
- nbr->v_holddown = EIGRP_HOLD_INTERVAL_DEFAULT;
- THREAD_OFF(nbr->t_holddown);
-
- /* out with the old */
- if (nbr->multicast_queue)
- eigrp_fifo_free (nbr->multicast_queue);
- if (nbr->retrans_queue)
- eigrp_fifo_free (nbr->retrans_queue);
-
- /* in with the new */
- nbr->retrans_queue = eigrp_fifo_new ();
- nbr->multicast_queue = eigrp_fifo_new ();
-
- nbr->crypt_seqnum = 0;
- }
+ nbr->state = state;
+
+ if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN) {
+ // reset all the seq/ack counters
+ nbr->recv_sequence_number = 0;
+ nbr->init_sequence_number = 0;
+ nbr->retrans_counter = 0;
+
+ // Kvalues
+ nbr->K1 = EIGRP_K1_DEFAULT;
+ nbr->K2 = EIGRP_K2_DEFAULT;
+ nbr->K3 = EIGRP_K3_DEFAULT;
+ nbr->K4 = EIGRP_K4_DEFAULT;
+ nbr->K5 = EIGRP_K5_DEFAULT;
+ nbr->K6 = EIGRP_K6_DEFAULT;
+
+ // hold time..
+ nbr->v_holddown = EIGRP_HOLD_INTERVAL_DEFAULT;
+ THREAD_OFF(nbr->t_holddown);
+
+ /* out with the old */
+ if (nbr->multicast_queue)
+ eigrp_fifo_free(nbr->multicast_queue);
+ if (nbr->retrans_queue)
+ eigrp_fifo_free(nbr->retrans_queue);
+
+ /* in with the new */
+ nbr->retrans_queue = eigrp_fifo_new();
+ nbr->multicast_queue = eigrp_fifo_new();
+
+ nbr->crypt_seqnum = 0;
+ }
}
-const char *
-eigrp_nbr_state_str (struct eigrp_neighbor *nbr)
+const char *eigrp_nbr_state_str(struct eigrp_neighbor *nbr)
{
- const char *state;
- switch (nbr->state)
- {
- case EIGRP_NEIGHBOR_DOWN:
- state = "Down";
- break;
- case EIGRP_NEIGHBOR_PENDING:
- state = "Waiting for Init";
- break;
- case EIGRP_NEIGHBOR_UP:
- state = "Up";
- break;
- default:
- state = "Unknown";
- break;
- }
-
- return(state);
+ const char *state;
+ switch (nbr->state) {
+ case EIGRP_NEIGHBOR_DOWN:
+ state = "Down";
+ break;
+ case EIGRP_NEIGHBOR_PENDING:
+ state = "Waiting for Init";
+ break;
+ case EIGRP_NEIGHBOR_UP:
+ state = "Up";
+ break;
+ default:
+ state = "Unknown";
+ break;
+ }
+
+ return (state);
}
-void
-eigrp_nbr_state_update (struct eigrp_neighbor *nbr)
+void eigrp_nbr_state_update(struct eigrp_neighbor *nbr)
{
- switch (nbr->state)
- {
- case EIGRP_NEIGHBOR_DOWN:
- {
- /*Start Hold Down Timer for neighbor*/
- // THREAD_OFF(nbr->t_holddown);
- // THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired,
- // nbr, nbr->v_holddown);
- break;
- }
- case EIGRP_NEIGHBOR_PENDING:
- {
- /*Reset Hold Down Timer for neighbor*/
- THREAD_OFF(nbr->t_holddown);
- thread_add_timer(master, holddown_timer_expired, nbr,
- nbr->v_holddown, &nbr->t_holddown);
- break;
- }
- case EIGRP_NEIGHBOR_UP:
- {
- /*Reset Hold Down Timer for neighbor*/
- THREAD_OFF(nbr->t_holddown);
- thread_add_timer(master, holddown_timer_expired, nbr,
- nbr->v_holddown, &nbr->t_holddown);
- break;
- }
- }
+ switch (nbr->state) {
+ case EIGRP_NEIGHBOR_DOWN: {
+ /*Start Hold Down Timer for neighbor*/
+ // THREAD_OFF(nbr->t_holddown);
+ // THREAD_TIMER_ON(master, nbr->t_holddown,
+ // holddown_timer_expired,
+ // nbr, nbr->v_holddown);
+ break;
+ }
+ case EIGRP_NEIGHBOR_PENDING: {
+ /*Reset Hold Down Timer for neighbor*/
+ THREAD_OFF(nbr->t_holddown);
+ thread_add_timer(master, holddown_timer_expired, nbr,
+ nbr->v_holddown, &nbr->t_holddown);
+ break;
+ }
+ case EIGRP_NEIGHBOR_UP: {
+ /*Reset Hold Down Timer for neighbor*/
+ THREAD_OFF(nbr->t_holddown);
+ thread_add_timer(master, holddown_timer_expired, nbr,
+ nbr->v_holddown, &nbr->t_holddown);
+ break;
+ }
+ }
}
-int eigrp_nbr_count_get(void){
- struct eigrp_interface *iface;
- struct listnode *node, *node2, *nnode2;
- struct eigrp_neighbor *nbr;
- struct eigrp *eigrp = eigrp_lookup();
- u_int32_t counter;
-
- if (eigrp == NULL)
- {
- zlog_debug("EIGRP Routing Process not enabled");
- return 0;
- }
-
- counter=0;
- for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface))
- {
- for (ALL_LIST_ELEMENTS(iface->nbrs, node2, nnode2, nbr))
- {
- if (nbr->state == EIGRP_NEIGHBOR_UP){
- counter++;
- }
- }
- }
- return counter;
+int eigrp_nbr_count_get(void)
+{
+ struct eigrp_interface *iface;
+ struct listnode *node, *node2, *nnode2;
+ struct eigrp_neighbor *nbr;
+ struct eigrp *eigrp = eigrp_lookup();
+ uint32_t counter;
+
+ if (eigrp == NULL) {
+ zlog_debug("EIGRP Routing Process not enabled");
+ return 0;
+ }
+
+ counter = 0;
+ for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) {
+ for (ALL_LIST_ELEMENTS(iface->nbrs, node2, nnode2, nbr)) {
+ if (nbr->state == EIGRP_NEIGHBOR_UP) {
+ counter++;
+ }
+ }
+ }
+ return counter;
}
/**
*/
void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty)
{
- if(nbr == NULL)
- {
- zlog_err("Nbr Hard restart: Neighbor not specified.");
- return;
- }
-
- zlog_debug ("Neighbor %s (%s) is down: manually cleared",
- inet_ntoa (nbr->src),
- ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT));
- if(vty != NULL)
- {
- vty_time_print (vty, 0);
- vty_outln (vty, "Neighbor %s (%s) is down: manually cleared",
- inet_ntoa (nbr->src),
- ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
- }
-
- /* send Hello with Peer Termination TLV */
- eigrp_hello_send(nbr->ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR, &(nbr->src));
- /* set neighbor to DOWN */
- nbr->state = EIGRP_NEIGHBOR_DOWN;
- /* delete neighbor */
- eigrp_nbr_delete (nbr);
+ if (nbr == NULL) {
+ flog_err(EC_EIGRP_CONFIG,
+ "Nbr Hard restart: Neighbor not specified.");
+ return;
+ }
+
+ zlog_debug("Neighbor %s (%s) is down: manually cleared",
+ inet_ntoa(nbr->src),
+ ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
+ if (vty != NULL) {
+ vty_time_print(vty, 0);
+ vty_out(vty, "Neighbor %s (%s) is down: manually cleared\n",
+ inet_ntoa(nbr->src),
+ ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
+ }
+
+ /* send Hello with Peer Termination TLV */
+ eigrp_hello_send(nbr->ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR,
+ &(nbr->src));
+ /* set neighbor to DOWN */
+ nbr->state = EIGRP_NEIGHBOR_DOWN;
+ /* delete neighbor */
+ eigrp_nbr_delete(nbr);
+}
+
+int eigrp_nbr_split_horizon_check(struct eigrp_nexthop_entry *ne,
+ struct eigrp_interface *ei)
+{
+ if (ne->distance == EIGRP_MAX_METRIC)
+ return 0;
+
+ return (ne->ei == ei);
}