]> git.proxmox.com Git - mirror_frr.git/blobdiff - eigrpd/eigrp_neighbor.c
zebra: Allow ns delete to happen after under/over flow checks
[mirror_frr.git] / eigrpd / eigrp_neighbor.c
index c0bb2afaf5237696be7fd33d3a5a82264241b448..66dd5f3419b0dc3d8fc1db1066fe4447e4a648ff 100644 (file)
 #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;
 }
 
 /**
@@ -78,41 +78,39 @@ eigrp_nbr_new (struct eigrp_interface *ei)
  * @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;
 }
 
 /**
@@ -127,21 +125,19 @@ eigrp_nbr_get (struct eigrp_interface *ei, struct eigrp_header *eigrph,
  * 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;
 }
 
 /**
@@ -156,188 +152,173 @@ eigrp_nbr_lookup_by_addr (struct eigrp_interface *ei, struct in_addr *addr)
  * 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;
 }
 
 /**
@@ -354,27 +335,36 @@ int eigrp_nbr_count_get(void){
  */
 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);
 }