/** * @fn eigrp_nbr_hard_restart * * @param[in] nbr Neighbor who would receive hard restart * @param[in] vty Virtual terminal for log output * @return void * * @par * Function used for executing hard restart for neighbor: * Send Hello packet with Peer Termination TLV with * neighbor's address, set it's state to DOWN and delete the neighbor */ 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)); if(vty != NULL) { vty_time_print (vty, 0); vty_out (vty, "Neighbor %s (%s) is down: manually cleared%s", inet_ntoa (nbr->src), ifindex2ifname (nbr->ei->ifp->ifindex), VTY_NEWLINE); } /* 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); }
static int bfd_ioctl_peer_info (struct bfd_nl_peerinfo *peer, struct vty *vty) { char buf1[BUFSIZ], buf2[BUFSIZ]; vty_out (vty, "%s", inet_ntop (peer->dst.sa.sa_family, peer->dst.sa.sa_family == AF_INET ? (char *) &peer->dst.sin.sin_addr : (char *) &peer->dst.sin6.sin6_addr, buf1, BUFSIZ)); vty_out (vty, " %u %u %s %s%s", ntohl (peer->my_disc), ntohl (peer->your_disc), bfd_state_string[peer->state], ifindex2ifname (peer->ifindex), VTY_NEWLINE); vty_out (vty, " SrcIP: %s%s", inet_ntop (peer->src.sa.sa_family, peer->src.sa.sa_family == AF_INET ? (char *) &peer->src.sin.sin_addr : (char *) &peer->src.sin6.sin6_addr, buf2, BUFSIZ), VTY_NEWLINE); vty_out (vty, " Packet Rcvd: %llu%s", peer->pkt_in, VTY_NEWLINE); vty_out (vty, " Packet Send: %llu%s", peer->pkt_out, VTY_NEWLINE); vty_out (vty, " Last UpTime(sysUptime): %u%s", peer->last_up, VTY_NEWLINE); vty_out (vty, " Last DownTime(sysUptime): %u%s", peer->last_down, VTY_NEWLINE); vty_out (vty, " Up Count: %u%s", peer->up_cnt, VTY_NEWLINE); return 0; }
/** * @fn eigrp_update_send_GR * * @param[in] nbr Neighbor who would receive Graceful restart * @param[in] gr_type Who executed Graceful restart * @param[in] vty Virtual terminal for log output * * @return void * * @par * Function used for sending Graceful restart Update packet: * Creates Update packet with INIT, RS, EOT flags and include * all route except those filtered */ void eigrp_update_send_GR (struct eigrp_neighbor *nbr, enum GR_type gr_type, struct vty *vty) { struct eigrp_prefix_entry *pe2; struct listnode *node2, *nnode2; struct list *prefixes; if(gr_type == EIGRP_GR_FILTER) { /* function was called after applying filtration */ zlog_info("Neighbor %s (%s) is resync: route configuration changed", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); } else if(gr_type == EIGRP_GR_MANUAL) { /* Graceful restart was called manually */ zlog_info("Neighbor %s (%s) is resync: manually cleared", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); if(vty != NULL) { vty_time_print (vty, 0); vty_out (vty, "Neighbor %s (%s) is resync: manually cleared%s", inet_ntoa (nbr->src), ifindex2ifname (nbr->ei->ifp->ifindex), VTY_NEWLINE); } } prefixes = list_new(); /* add all prefixes from topology table to list */ for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node2, nnode2, pe2)) { listnode_add(prefixes, pe2); } /* save prefixes to neighbor */ nbr->nbr_gr_prefixes_send = prefixes; /* indicate, that this is first GR Update packet chunk */ nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_FIRST; /* execute packet sending in thread */ nbr->t_nbr_send_gr = thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); }
static void print_nh (struct nexthop *nexthop, struct vty *vty) { char buf[BUFSIZ]; switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); if (nexthop->ifindex) vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex)); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6_IFNAME: vty_out (vty, " %s", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) vty_out (vty, ", %s", nexthop->ifname); else if (nexthop->ifindex) vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex)); break; case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " is directly connected, %s", ifindex2ifname (nexthop->ifindex)); break; case NEXTHOP_TYPE_IFNAME: vty_out (vty, " is directly connected, %s", nexthop->ifname); break; case NEXTHOP_TYPE_BLACKHOLE: vty_out (vty, " is directly connected, Null0"); break; default: break; } vty_out(vty, "%s", VTY_NEWLINE); }
int holddown_timer_expired (struct thread *thread) { struct eigrp_neighbor *nbr; nbr = THREAD_ARG (thread); zlog_info ("Neighbor %s (%s) is down: holding time expired", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); nbr->state = EIGRP_NEIGHBOR_DOWN; eigrp_nbr_delete (nbr); return 0; }
/* * EIGRP UPDATE read function */ void eigrp_update_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph, struct stream * s, struct eigrp_interface *ei, int size) { struct eigrp_neighbor *nbr; struct TLV_IPv4_Internal_type *tlv; struct eigrp_prefix_entry *pe; struct eigrp_neighbor_entry *ne; u_int32_t flags; u_int16_t type; uint16_t length; u_char same; struct access_list *alist; struct prefix_list *plist; struct eigrp *e; u_char graceful_restart; u_char graceful_restart_final; struct list *nbr_prefixes; int ret; /* increment statistics. */ ei->update_in++; /* get neighbor struct */ nbr = eigrp_nbr_get(ei, eigrph, iph); /* neighbor must be valid, eigrp_nbr_get creates if none existed */ assert(nbr); flags = ntohl(eigrph->flags); if (flags & EIGRP_CR_FLAG) { return; } same = 0; graceful_restart = 0; graceful_restart_final = 0; if((nbr->recv_sequence_number) == (ntohl(eigrph->sequence))) same = 1; nbr->recv_sequence_number = ntohl(eigrph->sequence); if (IS_DEBUG_EIGRP_PACKET(0, RECV)) zlog_debug("Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]", size, ifindex2ifname(nbr->ei->ifp->ifindex), inet_ntoa(nbr->src), nbr->recv_sequence_number, flags); if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG+EIGRP_EOT_FLAG)) && (!same)) { /* Graceful restart Update received with all routes */ zlog_info("Neighbor %s (%s) is resync: peer graceful-restart", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); /* get all prefixes from neighbor from topology table */ nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr); graceful_restart = 1; graceful_restart_final = 1; } else if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG)) && (!same)) { /* Graceful restart Update received, routes also in next packet */ zlog_info("Neighbor %s (%s) is resync: peer graceful-restart", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); /* get all prefixes from neighbor from topology table */ nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr); /* save prefixes to neighbor for later use */ nbr->nbr_gr_prefixes = nbr_prefixes; graceful_restart = 1; graceful_restart_final = 0; } else if((flags == (EIGRP_EOT_FLAG)) && (!same)) { /* If there was INIT+RS Update packet before, * consider this as GR EOT */ if(nbr->nbr_gr_prefixes != NULL) { /* this is final packet of GR */ nbr_prefixes = nbr->nbr_gr_prefixes; nbr->nbr_gr_prefixes = NULL; graceful_restart = 1; graceful_restart_final = 1; } } else if((flags == (0)) && (!same)) { /* If there was INIT+RS Update packet before, * consider this as GR not final packet */ if(nbr->nbr_gr_prefixes != NULL) { /* this is GR not final route packet */ nbr_prefixes = nbr->nbr_gr_prefixes; graceful_restart = 1; graceful_restart_final = 0; } } else if((flags & EIGRP_INIT_FLAG) && (!same)) { /* When in pending state, send INIT update only if it wasn't already sent before (only if init_sequence is 0) */ if((nbr->state == EIGRP_NEIGHBOR_PENDING) && (nbr->init_sequence_number == 0)) eigrp_update_send_init(nbr); if (nbr->state == EIGRP_NEIGHBOR_UP) { eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN); eigrp_topology_neighbor_down(nbr->ei->eigrp,nbr); nbr->recv_sequence_number = ntohl(eigrph->sequence); zlog_info("Neighbor %s (%s) is down: peer restarted", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING); zlog_info("Neighbor %s (%s) is pending: new adjacency", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); eigrp_update_send_init(nbr); } } /*If there is topology information*/ while (s->endp > s->getp) { type = stream_getw(s); if (type == EIGRP_TLV_IPv4_INT) { stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); /*searching if destination exists */ struct prefix_ipv4 *dest_addr; dest_addr = prefix_ipv4_new(); dest_addr->prefix = tlv->destination; dest_addr->prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( eigrp->topology_table, dest_addr); /*if exists it comes to DUAL*/ if (dest != NULL) { /* remove received prefix from neighbor prefix list if in GR */ if(graceful_restart) remove_received_prefix_gr(nbr_prefixes, dest); struct eigrp_fsm_action_message *msg; msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, sizeof(struct eigrp_fsm_action_message)); struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); msg->packet_type = EIGRP_OPC_UPDATE; msg->eigrp = eigrp; msg->data_type = EIGRP_TLV_IPv4_INT; msg->adv_router = nbr; msg->data.ipv4_int_type = tlv; msg->entry = entry; msg->prefix = dest; int event = eigrp_get_fsm_event(msg); eigrp_fsm_event(msg, event); } else { /*Here comes topology information save*/ pe = eigrp_prefix_entry_new(); pe->serno = eigrp->serno; pe->destination_ipv4 = dest_addr; pe->af = AF_INET; pe->state = EIGRP_FSM_STATE_PASSIVE; pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE; ne = eigrp_neighbor_entry_new(); ne->ei = ei; ne->adv_router = nbr; ne->reported_metric = tlv->metric; ne->reported_distance = eigrp_calculate_metrics(eigrp, &tlv->metric); //TODO: Work in progress /* * Filtering */ e = eigrp_lookup(); /* get access-list from eigrp process */ alist = e->list[EIGRP_FILTER_IN]; zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix)); if (alist) { zlog_info ("ALIST PROC IN: %s", alist->name); } else { zlog_info("ALIST PROC IN je prazdny"); } /* Check if access-list fits */ if (alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ zlog_info("PROC alist IN: Skipping"); //ne->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix)); eigrp_IPv4_InternalTLV_free (tlv); continue; } else { zlog_info("PROC alist IN: NENastavujem metriku "); } plist = e->prefix[EIGRP_FILTER_IN]; if (plist) { zlog_info ("PLIST PROC IN: %s", plist->name); } else { zlog_info("PLIST PROC IN je prazdny"); } /* Check if prefix-list fits */ if (plist && prefix_list_apply (plist, (struct prefix *) dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ zlog_info("PLIST PROC IN: Skipping"); //ne->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("PLIST PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix)); eigrp_IPv4_InternalTLV_free (tlv); continue; } else { zlog_info("PLIST PROC IN: NENastavujem metriku "); } //Check route-map /*if (e->routemap[EIGRP_FILTER_IN]) { ret = route_map_apply (e->routemap[EIGRP_FILTER_IN], (struct prefix *)dest_addr, RMAP_EIGRP, NULL); if (ret == RMAP_DENYMATCH) { zlog_debug ("%s is filtered by route-map",inet_ntoa (dest_addr->prefix)); continue; } }*/ /*Get access-list from current interface */ zlog_info("Checking access_list on interface: %s",ei->ifp->name); alist = ei->list[EIGRP_FILTER_IN]; if (alist) { zlog_info ("ALIST INT IN: %s", alist->name); } else { zlog_info("ALIST INT IN je prazdny"); } /* Check if access-list fits */ if (alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ zlog_info("INT alist IN: Skipping"); //ne->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("INT IN Prefix: %s", inet_ntoa(dest_addr->prefix)); eigrp_IPv4_InternalTLV_free (tlv); continue; } else { zlog_info("INT IN: NENastavujem metriku "); } plist = ei->prefix[EIGRP_FILTER_IN]; if (plist) { zlog_info ("PLIST INT IN: %s", plist->name); } else { zlog_info("PLIST INT IN je prazdny"); } /* Check if prefix-list fits */ if (plist && prefix_list_apply (plist, (struct prefix *) dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ zlog_info("PLIST INT IN: Skipping"); //ne->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("PLIST INT IN Prefix: %s", inet_ntoa(dest_addr->prefix)); eigrp_IPv4_InternalTLV_free (tlv); continue; } else { zlog_info("PLIST INT IN: NENastavujem metriku "); } //Check route-map /*if (ei->routemap[EIGRP_FILTER_IN]) { ret = route_map_apply (ei->routemap[EIGRP_FILTER_IN], (struct prefix *)dest_addr, RMAP_EIGRP, NULL); if (ret == RMAP_DENYMATCH) { zlog_debug ("%s is filtered by route-map",inet_ntoa (dest_addr->prefix)); continue; } }*/ /* * End of filtering */ ne->distance = eigrp_calculate_total_metrics(eigrp, ne); zlog_info("<DEBUG PROC IN Distance: %x", ne->distance); zlog_info("<DEBUG PROC IN Delay: %x", ne->total_metric.delay); pe->fdistance = pe->distance = pe->rdistance = ne->distance; ne->prefix = pe; ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; eigrp_prefix_entry_add(eigrp->topology_table, pe); eigrp_neighbor_entry_add(pe, ne); pe->distance = pe->fdistance = pe->rdistance = ne->distance; pe->reported_metric = ne->total_metric; eigrp_topology_update_node_flags(pe); pe->req_action |= EIGRP_FSM_NEED_UPDATE; listnode_add(eigrp->topology_changes_internalIPV4, pe); } eigrp_IPv4_InternalTLV_free (tlv); } } /* ask about prefixes not present in GR update, * if this is final GR packet */ if(graceful_restart_final) { eigrp_update_receive_GR_ask(eigrp, nbr, nbr_prefixes); } /* * We don't need to send separate Ack for INIT Update. INIT will be acked in EOT Update. */ if ((nbr->state == EIGRP_NEIGHBOR_UP) && !(flags == EIGRP_INIT_FLAG)) { eigrp_hello_send_ack(nbr); } eigrp_query_send_all(eigrp); eigrp_update_send_all(eigrp, ei); }
static int show_ip_bgp_nexthop_table (struct vty *vty, int detail) { struct bgp_node *rn; struct bgp_nexthop_cache *bnc; char buf[INET6_ADDRSTRLEN]; struct nexthop *nexthop; time_t tbuf; afi_t afi; vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE); for (afi = AFI_IP ; afi < AFI_MAX ; afi++) { if (!bgp_nexthop_cache_table[afi]) continue; for (rn = bgp_table_top (bgp_nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn)) { if ((bnc = rn->info) != NULL) { if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) { vty_out (vty, " %s valid [IGP metric %d], #paths %d%s", inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)), bnc->metric, bnc->path_count, VTY_NEWLINE); if (detail) for (nexthop = bnc->nexthop ; nexthop; nexthop = nexthop->next) switch (nexthop->type) { case NEXTHOP_TYPE_IPV6: vty_out (vty, " gate %s%s", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE); break; case NEXTHOP_TYPE_IPV6_IFINDEX: vty_out(vty, " gate %s, if %s%s", inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, INET6_ADDRSTRLEN), ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); break; case NEXTHOP_TYPE_IPV4: vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &nexthop->gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE); break; case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " if %s%s", ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); break; case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " gate %s, if %s%s", inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, INET6_ADDRSTRLEN), ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); break; default: vty_out (vty, " invalid nexthop type %u%s", nexthop->type, VTY_NEWLINE); } } else vty_out (vty, " %s invalid%s", inet_ntop (AF_INET, &rn->p.u.prefix, buf, sizeof (buf)), VTY_NEWLINE); #ifdef HAVE_CLOCK_MONOTONIC tbuf = time(NULL) - (bgp_clock() - bnc->last_update); vty_out (vty, " Last update: %s", ctime(&tbuf)); #else vty_out (vty, " Last update: %s", ctime(&bnc->uptime)); #endif /* HAVE_CLOCK_MONOTONIC */ vty_out(vty, "%s", VTY_NEWLINE); } } } return CMD_SUCCESS; }
static int fib_lookup_if_vif_index(struct in_addr addr) { struct pim_zlookup_nexthop nexthop_tab[PIM_NEXTHOP_IFINDEX_TAB_SIZE]; int num_ifindex; int vif_index; int first_ifindex; num_ifindex = zclient_lookup_nexthop(qpim_zclient_lookup, nexthop_tab, PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr, PIM_NEXTHOP_LOOKUP_MAX); if (num_ifindex < 1) { char addr_str[100]; pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: could not find nexthop ifindex for address %s", __FILE__, __PRETTY_FUNCTION__, addr_str); return -1; } first_ifindex = nexthop_tab[0].ifindex; if (num_ifindex > 1) { char addr_str[100]; pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); zlog_info("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)", __FILE__, __PRETTY_FUNCTION__, num_ifindex, addr_str, first_ifindex); /* debug warning only, do not return */ } if (PIM_DEBUG_ZEBRA) { char addr_str[100]; pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str)); zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s", __FILE__, __PRETTY_FUNCTION__, first_ifindex, ifindex2ifname(first_ifindex), addr_str); } vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); if (vif_index < 1) { char addr_str[100]; pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: low vif_index=%d < 1 nexthop for address %s", __FILE__, __PRETTY_FUNCTION__, vif_index, addr_str); return -2; } zassert(qpim_mroute_oif_highest_vif_index < MAXVIFS); if (vif_index > qpim_mroute_oif_highest_vif_index) { char addr_str[100]; pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); zlog_warn("%s %s: high vif_index=%d > highest_vif_index=%d nexthop for address %s", __FILE__, __PRETTY_FUNCTION__, vif_index, qpim_mroute_oif_highest_vif_index, addr_str); zlog_warn("%s %s: pim disabled on interface %s vif_index=%d ?", __FILE__, __PRETTY_FUNCTION__, ifindex2ifname(vif_index), vif_index); return -3; } return vif_index; }