static int eigrp_neighbor_packet_queue_sum(struct eigrp_interface *ei)
{
struct eigrp_neighbor *nbr;
- struct listnode *node, *nnode;
int sum;
+
sum = 0;
- for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
sum += nbr->retrans_queue->count;
}
vty_out(vty, "%-16s ", IF_NAME(ei));
vty_out(vty, "%-11u", ei->params.bandwidth);
vty_out(vty, "%-11u", ei->params.delay);
- vty_out(vty, "%-7u", ei->nbrs->count);
+ vty_out(vty, "%-7zu", eigrp_nbr_hash_count(&ei->nbr_hash_head));
vty_out(vty, "%u %c %-10u", 0, '/',
eigrp_neighbor_packet_queue_sum(ei));
vty_out(vty, "%-7u %-14u %-12u %-8u", 0, 0, 0, 0);
{
uint16_t length = EIGRP_TLV_SEQ_BASE_LEN;
struct eigrp_interface *ei;
- struct listnode *node, *node2, *nnode2;
+ struct listnode *node;
struct eigrp_neighbor *nbr;
size_t backup_end, size_end;
int found;
found = 0;
for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
- for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
if (nbr->multicast_queue->count > 0) {
length += (uint16_t)stream_put_ipv4(
s, nbr->src.s_addr);
ei->type = EIGRP_IFTYPE_BROADCAST;
/* Initialize neighbor list. */
- ei->nbrs = list_new();
+ eigrp_nbr_hash_init(&ei->nbr_hash_head);
ei->crypt_seqnum = frr_sequence32_next();
if (!ei)
return 0;
- list_delete(&ei->nbrs);
+ eigrp_nbr_hash_fini(&ei->nbr_hash_head);
eigrp = ei->eigrp;
listnode_delete(eigrp->eiflist, ei);
int eigrp_if_down(struct eigrp_interface *ei)
{
- struct listnode *node, *nnode;
- struct eigrp_neighbor *nbr;
-
if (ei == NULL)
return 0;
/*Set infinite metrics to routes learned by this interface and start
* query process*/
- for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
- eigrp_nbr_delete(nbr);
- }
+ while (eigrp_nbr_hash_count(&ei->nbr_hash_head) > 0)
+ eigrp_nbr_delete(eigrp_nbr_hash_first(&ei->nbr_hash_head));
+
return 1;
}
DEFINE_MTYPE_STATIC(EIGRPD, EIGRP_NEIGHBOR, "EIGRP neighbor");
+int eigrp_nbr_comp(const struct eigrp_neighbor *a, const struct eigrp_neighbor *b)
+{
+ if (a->src.s_addr == b->src.s_addr)
+ return 0;
+ else if (a->src.s_addr < b->src.s_addr)
+ return -1;
+
+ return 1;
+}
+
+uint32_t eigrp_nbr_hash(const struct eigrp_neighbor *a)
+{
+ return a->src.s_addr;
+}
+
struct eigrp_neighbor *eigrp_nbr_new(struct eigrp_interface *ei)
{
struct eigrp_neighbor *nbr;
struct eigrp_header *eigrph,
struct ip *iph)
{
- struct eigrp_neighbor *nbr;
- struct listnode *node, *nnode;
+ struct eigrp_neighbor lookup, *nbr;
- for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
- if (iph->ip_src.s_addr == nbr->src.s_addr) {
- return nbr;
- }
+ lookup.src = iph->ip_src;
+ lookup.ei = ei;
+
+ nbr = eigrp_nbr_hash_find(&ei->nbr_hash_head, &lookup);
+ if (nbr) {
+ return nbr;
}
nbr = eigrp_nbr_add(ei, eigrph, iph);
- listnode_add(ei->nbrs, nbr);
+ eigrp_nbr_hash_add(&ei->nbr_hash_head, nbr);
return nbr;
}
struct eigrp_neighbor *eigrp_nbr_lookup_by_addr(struct eigrp_interface *ei,
struct in_addr *addr)
{
- struct eigrp_neighbor *nbr;
- struct listnode *node, *nnode;
+ struct eigrp_neighbor lookup, *nbr;
- for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
- if (addr->s_addr == nbr->src.s_addr) {
- return nbr;
- }
- }
+ lookup.src = *addr;
+ nbr = eigrp_nbr_hash_find(&ei->nbr_hash_head, &lookup);
- return NULL;
+ return nbr;
}
/**
struct in_addr nbr_addr)
{
struct eigrp_interface *ei;
- struct listnode *node, *node2, *nnode2;
- struct eigrp_neighbor *nbr;
+ struct listnode *node;
+ struct eigrp_neighbor lookup, *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;
- }
+ lookup.src = nbr_addr;
+ nbr = eigrp_nbr_hash_find(&ei->nbr_hash_head, &lookup);
+ if (nbr) {
+ return nbr;
}
}
EVENT_OFF(nbr->t_holddown);
if (nbr->ei)
- listnode_delete(nbr->ei->nbrs, nbr);
+ eigrp_nbr_hash_del(&nbr->ei->nbr_hash_head, nbr);
XFREE(MTYPE_EIGRP_NEIGHBOR, nbr);
}
int eigrp_nbr_count_get(struct eigrp *eigrp)
{
struct eigrp_interface *iface;
- struct listnode *node, *node2, *nnode2;
- struct eigrp_neighbor *nbr;
+ struct listnode *node;
uint32_t counter;
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++;
- }
- }
- }
+ for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface))
+ counter += eigrp_nbr_hash_count(&iface->nbr_hash_head);
+
return counter;
}
extern int eigrp_nbr_split_horizon_check(struct eigrp_route_descriptor *ne,
struct eigrp_interface *ei);
+
+extern int eigrp_nbr_comp(const struct eigrp_neighbor *a, const struct eigrp_neighbor *b);
+extern uint32_t eigrp_nbr_hash(const struct eigrp_neighbor *a);
+
+DECLARE_HASH(eigrp_nbr_hash, struct eigrp_neighbor, nbr_hash_item, eigrp_nbr_comp, eigrp_nbr_hash);
#endif /* _ZEBRA_EIGRP_NEIGHBOR_H */
{
struct eigrp_packet *ep = NULL;
uint16_t length = EIGRP_HEADER_LEN;
- struct listnode *node, *nnode, *node2, *nnode2;
+ struct listnode *node, *nnode;
struct eigrp_neighbor *nbr;
struct eigrp_prefix_descriptor *pe;
bool has_tlv = false;
length += eigrp_add_internalTLV_to_stream(ep->s, pe);
has_tlv = true;
- for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
if (nbr->state == EIGRP_NEIGHBOR_UP)
listnode_add(pe->rij, nbr);
}
ep->sequence_number = ei->eigrp->sequence_number;
ei->eigrp->sequence_number++;
- for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
struct eigrp_packet *dup;
if (nbr->state != EIGRP_NEIGHBOR_UP)
ep->sequence_number = ei->eigrp->sequence_number;
ei->eigrp->sequence_number++;
- for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
struct eigrp_packet *dup;
if (nbr->state != EIGRP_NEIGHBOR_UP)
MEMBER_MAX,
};
+PREDECL_HASH(eigrp_nbr_hash);
+
/*EIGRP interface structure*/
struct eigrp_interface {
struct eigrp_if_params params;
struct prefix address; /* Interface prefix */
/* Neighbor information. */
- struct list *nbrs; /* EIGRP Neighbor List */
+ struct eigrp_nbr_hash_head nbr_hash_head;
/* Threads. */
struct event *t_hello; /* timer */
/* Neighbor Data Structure */
struct eigrp_neighbor {
+ struct eigrp_nbr_hash_item nbr_hash_item;
+
/* This neighbor's parent eigrp interface. */
struct eigrp_interface *ei;
static void eigrp_update_send_to_all_nbrs(struct eigrp_interface *ei,
struct eigrp_packet *ep)
{
- struct listnode *node, *nnode;
struct eigrp_neighbor *nbr;
bool packet_sent = false;
- for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
struct eigrp_packet *ep_dup;
if (nbr->state != EIGRP_NEIGHBOR_UP)
uint32_t seq_no = eigrp->sequence_number;
uint16_t eigrp_mtu = EIGRP_PACKET_MTU(ei->ifp->mtu);
- if (ei->nbrs->count == 0)
+ if (eigrp_nbr_hash_count(&ei->nbr_hash_head) == 0)
return;
uint16_t length = EIGRP_HEADER_LEN;
void eigrp_update_send_interface_GR(struct eigrp_interface *ei,
enum GR_type gr_type, struct vty *vty)
{
- struct listnode *node;
struct eigrp_neighbor *nbr;
/* iterate over all neighbors on eigrp interface */
- for (ALL_LIST_ELEMENTS_RO(ei->nbrs, node, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
/* send GR to neighbor */
eigrp_update_send_GR(nbr, gr_type, vty);
}
const char *ifname, const char *detail)
{
struct eigrp_interface *ei;
- struct listnode *node, *node2, *nnode2;
+ struct listnode *node;
struct eigrp_neighbor *nbr;
show_ip_eigrp_neighbor_header(vty, eigrp);
for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
if (!ifname || strcmp(ei->ifp->name, ifname) == 0) {
- for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
if (detail || (nbr->state == EIGRP_NEIGHBOR_UP))
show_ip_eigrp_neighbor_sub(vty, nbr,
!!detail);
{
struct eigrp *eigrp;
struct eigrp_interface *ei;
- struct listnode *node, *node2, *nnode2;
+ struct listnode *node;
struct eigrp_neighbor *nbr;
/* Check if eigrp process is enabled */
eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
/* iterate over all neighbors on eigrp interface */
- for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
if (nbr->state != EIGRP_NEIGHBOR_DOWN) {
zlog_debug(
"Neighbor %pI4 (%s) is down: manually cleared",
{
struct eigrp *eigrp;
struct eigrp_interface *ei;
- struct listnode *node2, *nnode2;
struct eigrp_neighbor *nbr;
/* Check if eigrp process is enabled */
eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
/* iterate over all neighbors on eigrp interface */
- for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
+ frr_each (eigrp_nbr_hash, &ei->nbr_hash_head, nbr) {
if (nbr->state != EIGRP_NEIGHBOR_DOWN) {
zlog_debug(
"Neighbor %pI4 (%s) is down: manually cleared",
{
struct eigrp_interface *ei;
struct eigrp_neighbor *nbr;
- struct listnode *node, *nnode, *node2, *nnode2;
+ struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei)) {
- for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr))
+ while (eigrp_nbr_hash_count(&ei->nbr_hash_head)) {
+ nbr = eigrp_nbr_hash_first(&ei->nbr_hash_head);
eigrp_nbr_delete(nbr);
+ }
eigrp_if_free(ei, INTERFACE_DOWN_BY_FINAL);
}