diff --git a/eigrpd/eigrp_const.h b/eigrpd/eigrp_const.h index 3fa59756b7..c5f6e64d0b 100644 --- a/eigrpd/eigrp_const.h +++ b/eigrpd/eigrp_const.h @@ -153,14 +153,37 @@ enum eigrp_fsm_states { #define EIGRP_FSM_NEED_QUERY 2 /*EIGRP FSM events*/ -#define EIGRP_FSM_EVENT_NQ_FCN 0 /*input event other than query from succ, FC not satisfied*/ -#define EIGRP_FSM_EVENT_LR 1 /*last reply, FD is reset*/ -#define EIGRP_FSM_EVENT_Q_FCN 2 /*query from succ, FC not satisfied*/ -#define EIGRP_FSM_EVENT_LR_FCS 3 /*last reply, FC satisfied with current value of FDij*/ -#define EIGRP_FSM_EVENT_DINC 4 /*distance increase while in active state*/ -#define EIGRP_FSM_EVENT_QACT 5 /*query from succ while in active state*/ -#define EIGRP_FSM_EVENT_LR_FCN 6 /*last reply, FC not satisfied with current value of FDij*/ -#define EIGRP_FSM_KEEP_STATE 7 /*state not changed, usually by receiving not last reply */ +enum eigrp_fsm_events { + /* + * Input event other than query from succ, + * FC is not satisified + */ + EIGRP_FSM_EVENT_NQ_FCN, + + /* last reply, FD is reset */ + EIGRP_FSM_EVENT_LR, + + /* Query from succ, FC not satisfied */ + EIGRP_FSM_EVENT_Q_FCN, + + /* last reply, FC satisifed with current value of FDij */ + EIGRP_FSM_EVENT_LR_FCS, + + /* distance increase while in a active state */ + EIGRP_FSM_EVENT_DINC, + + /* Query from succ while in active state */ + EIGRP_FSM_EVENT_QACT, + + /* last reply, FC not satisified */ + EIGRP_FSM_EVENT_LR_FCN, + + /* + * state not changed + * usually by receiving not last reply + */ + EIGRP_FSM_KEEP_STATE, +}; /** * External routes originate from some other protocol - these are them diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c index 29357c2b24..b4978bc06f 100644 --- a/eigrpd/eigrp_fsm.c +++ b/eigrpd/eigrp_fsm.c @@ -170,6 +170,85 @@ struct { }, }; +static const char *packet_type2str(u_char packet_type) +{ + if (packet_type == EIGRP_OPC_UPDATE) + return "Update"; + if (packet_type == EIGRP_OPC_REQUEST) + return "Request"; + if (packet_type == EIGRP_OPC_QUERY) + return "Query"; + if (packet_type == EIGRP_OPC_REPLY) + return "Reply"; + if (packet_type == EIGRP_OPC_HELLO) + return "Hello"; + if (packet_type == EIGRP_OPC_IPXSAP) + return "IPXSAP"; + if (packet_type == EIGRP_OPC_ACK) + return "Ack"; + if (packet_type == EIGRP_OPC_SIAQUERY) + return "SIA Query"; + if (packet_type == EIGRP_OPC_SIAREPLY) + return "SIA Reply"; + + return "Unknown"; +} + +static const char *prefix_state2str(enum eigrp_fsm_states state) +{ + switch (state) { + case EIGRP_FSM_STATE_PASSIVE: + return "Passive"; + case EIGRP_FSM_STATE_ACTIVE_0: + return "Active oij0"; + case EIGRP_FSM_STATE_ACTIVE_1: + return "Active oij1"; + case EIGRP_FSM_STATE_ACTIVE_2: + return "Active oij2"; + case EIGRP_FSM_STATE_ACTIVE_3: + return "Active oij3"; + } + + return "Unknown"; +} + +static const char *fsm_state2str(enum eigrp_fsm_events event) +{ + switch (event) { + case EIGRP_FSM_KEEP_STATE: + return "Keep State Event"; + case EIGRP_FSM_EVENT_NQ_FCN: + return "Non Query Event Feasability not satisfied"; + case EIGRP_FSM_EVENT_LR: + return "Last Reply Event"; + case EIGRP_FSM_EVENT_Q_FCN: + return "Query Event Feasability not satisified"; + case EIGRP_FSM_EVENT_LR_FCS: + return "Last Reply Event Feasability satisified"; + case EIGRP_FSM_EVENT_DINC: + return "Distance Increase Event"; + case EIGRP_FSM_EVENT_QACT: + return "Query from Successor while in active state"; + case EIGRP_FSM_EVENT_LR_FCN: + return "Last Reply Event, Feasibility not satisfied"; + }; + + return "Unknown"; +} + +static const char *change2str(enum metric_change change) +{ + switch (change) { + case METRIC_DECREASE: + return "Decrease"; + case METRIC_SAME: + return "Same"; + case METRIC_INCREASE: + return "Increase"; + } + + return "Unknown"; +} /* * Main function in which are make decisions which event occurred. * msg - argument of type struct eigrp_fsm_action_message contain @@ -178,7 +257,8 @@ struct { * Return number of occurred event (arrow in diagram). * */ -static int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) +static enum eigrp_fsm_events eigrp_get_fsm_event( + struct eigrp_fsm_action_message *msg) { // Loading base information from message // struct eigrp *eigrp = msg->eigrp; @@ -201,6 +281,9 @@ static int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) */ change = eigrp_topology_update_distance(msg); + /* Store for display later */ + msg->change = change; + switch (actual_state) { case EIGRP_FSM_STATE_PASSIVE: { struct eigrp_nexthop_entry *head = @@ -265,7 +348,8 @@ static int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) zlog_info("All reply received\n"); return EIGRP_FSM_EVENT_LR; } - } else if (msg->packet_type == EIGRP_OPC_UPDATE && change == 1 + } else if (msg->packet_type == EIGRP_OPC_UPDATE + && change == METRIC_INCREASE && (entry->flags & EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG)) { return EIGRP_FSM_EVENT_DINC; @@ -310,7 +394,8 @@ static int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) zlog_info("All reply received\n"); return EIGRP_FSM_EVENT_LR; } - } else if (msg->packet_type == EIGRP_OPC_UPDATE && change == 1 + } else if (msg->packet_type == EIGRP_OPC_UPDATE + && change == METRIC_INCREASE && (entry->flags & EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG)) { return EIGRP_FSM_EVENT_DINC; @@ -330,10 +415,15 @@ static int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) */ int eigrp_fsm_event(struct eigrp_fsm_action_message *msg) { - int event = eigrp_get_fsm_event(msg); - zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s", - msg->eigrp->AS, msg->prefix->state, event, - eigrp_topology_ip_string(msg->prefix)); + enum eigrp_fsm_events event = eigrp_get_fsm_event(msg); + + zlog_info("EIGRP AS: %d State: %s Event: %s Network: %s Packet Type: %s Reply RIJ Count: %d change: %s", + msg->eigrp->AS, prefix_state2str(msg->prefix->state), + fsm_state2str(event), + eigrp_topology_ip_string(msg->prefix), + packet_type2str(msg->packet_type), + msg->prefix->rij->count, + change2str(msg->change)); (*(NSM[msg->prefix->state][event].func))(msg); return 1; diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 83ff194729..5b54f81326 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -344,8 +344,18 @@ int eigrp_write(struct thread *thread) /* Get one packet from queue. */ ep = eigrp_fifo_next(ei->obuf); - assert(ep); - assert(ep->length >= EIGRP_HEADER_LEN); + if (!ep) { + zlog_err("%s: Interface %s no packet on queue?", + __PRETTY_FUNCTION__, ei->ifp->name); + goto out; + } + if (ep->length < EIGRP_HEADER_LEN) { + zlog_err("%s: Packet just has a header?", + __PRETTY_FUNCTION__); + eigrp_header_dump((struct eigrp_header *)ep->s->data); + eigrp_packet_delete(ei); + goto out; + } if (ep->dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) eigrp_if_ipmulticast(eigrp, ei->address, ei->ifp->ifindex); @@ -442,6 +452,7 @@ int eigrp_write(struct thread *thread) /* Now delete packet from queue. */ eigrp_packet_delete(ei); +out: if (eigrp_fifo_next(ei->obuf) == NULL) { ei->on_write_q = 0; list_delete_node(eigrp->oi_write_q, node); diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index 88a592e6c9..caa37870a1 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -165,7 +165,7 @@ void eigrp_send_query(struct eigrp_interface *ei) struct listnode *node, *nnode, *node2, *nnode2; struct eigrp_neighbor *nbr; struct eigrp_prefix_entry *pe; - char has_tlv; + bool has_tlv = false; bool ep_saved = false; ep = eigrp_packet_new(ei->ifp->mtu, NULL); @@ -180,16 +180,16 @@ void eigrp_send_query(struct eigrp_interface *ei) length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei); } - has_tlv = 0; for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe)) { - if (pe->req_action & EIGRP_FSM_NEED_QUERY) { - length += eigrp_add_internalTLV_to_stream(ep->s, pe); - for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { - if (nbr->state == EIGRP_NEIGHBOR_UP) { - listnode_add(pe->rij, nbr); - has_tlv = 1; - } + if (!(pe->req_action & EIGRP_FSM_NEED_QUERY)) + continue; + + length += eigrp_add_internalTLV_to_stream(ep->s, pe); + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (nbr->state == EIGRP_NEIGHBOR_UP) { + listnode_add(pe->rij, nbr); + has_tlv = true;; } } } @@ -212,6 +212,7 @@ void eigrp_send_query(struct eigrp_interface *ei) /*This ack number we await from neighbor*/ ep->sequence_number = ei->eigrp->sequence_number; + ei->eigrp->sequence_number++; for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { if (nbr->state == EIGRP_NEIGHBOR_UP) { diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index 8dbd1a5b35..0ccffde72b 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -149,49 +149,56 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, while (s->endp > s->getp) { type = stream_getw(s); - if (type == EIGRP_TLV_IPv4_INT) { - struct prefix dest_addr; - stream_set_getp(s, s->getp - sizeof(u_int16_t)); + if (type != EIGRP_TLV_IPv4_INT) + continue; - tlv = eigrp_read_ipv4_tlv(s); + struct prefix dest_addr; - dest_addr.family = AF_INET; - dest_addr.u.prefix4 = tlv->destination; - dest_addr.prefixlen = tlv->prefix_length; - struct eigrp_prefix_entry *dest = - eigrp_topology_table_lookup_ipv4( - eigrp->topology_table, &dest_addr); - /* - * Destination must exists - */ - assert(dest); + stream_set_getp(s, s->getp - sizeof(u_int16_t)); - struct eigrp_fsm_action_message msg; - struct eigrp_nexthop_entry *entry = - eigrp_prefix_entry_lookup(dest->entries, nbr); + tlv = eigrp_read_ipv4_tlv(s); - if (eigrp_update_prefix_apply(eigrp, ei, - EIGRP_FILTER_IN, - &dest_addr)) { - tlv->metric.delay = EIGRP_MAX_METRIC; - } - /* - * End of filtering - */ - - msg.packet_type = EIGRP_OPC_REPLY; - msg.eigrp = eigrp; - msg.data_type = EIGRP_INT; - msg.adv_router = nbr; - msg.metrics = tlv->metric; - msg.entry = entry; - msg.prefix = dest; - eigrp_fsm_event(&msg); - - - eigrp_IPv4_InternalTLV_free(tlv); + dest_addr.family = AF_INET; + dest_addr.u.prefix4 = tlv->destination; + dest_addr.prefixlen = tlv->prefix_length; + struct eigrp_prefix_entry *dest = + eigrp_topology_table_lookup_ipv4( + eigrp->topology_table, &dest_addr); + /* + * Destination must exists + */ + if (!dest) { + char buf[PREFIX_STRLEN]; + zlog_err("%s: Received prefix %s which we do not know about", + __PRETTY_FUNCTION__, + prefix2str(&dest_addr, buf, strlen(buf))); + continue; } + + struct eigrp_fsm_action_message msg; + struct eigrp_nexthop_entry *entry = + eigrp_prefix_entry_lookup(dest->entries, nbr); + + if (eigrp_update_prefix_apply(eigrp, ei, + EIGRP_FILTER_IN, + &dest_addr)) { + tlv->metric.delay = EIGRP_MAX_METRIC; + } + /* + * End of filtering + */ + + msg.packet_type = EIGRP_OPC_REPLY; + msg.eigrp = eigrp; + msg.data_type = EIGRP_INT; + msg.adv_router = nbr; + msg.metrics = tlv->metric; + msg.entry = entry; + msg.prefix = dest; + eigrp_fsm_event(&msg); + + eigrp_IPv4_InternalTLV_free(tlv); } eigrp_hello_send_ack(nbr); } diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h index 324181c21e..aae56c8ffe 100644 --- a/eigrpd/eigrp_structs.h +++ b/eigrpd/eigrp_structs.h @@ -499,6 +499,7 @@ struct eigrp_fsm_action_message { struct eigrp_prefix_entry *prefix; msg_data_t data_type; // internal or external tlv type struct eigrp_metrics metrics; + enum metric_change change; }; #endif /* _ZEBRA_EIGRP_STRUCTURES_H_ */ diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c index 42d398458e..fd7a233238 100644 --- a/eigrpd/eigrpd.c +++ b/eigrpd/eigrpd.c @@ -284,14 +284,15 @@ void eigrp_finish_final(struct eigrp *eigrp) list_delete_and_null(&eigrp->eiflist); list_delete_and_null(&eigrp->oi_write_q); - list_delete_and_null(&eigrp->topology_changes_externalIPV4); - list_delete_and_null(&eigrp->topology_changes_internalIPV4); eigrp_topology_cleanup(eigrp->topology_table); eigrp_topology_free(eigrp->topology_table); eigrp_nbr_delete(eigrp->neighbor_self); + list_delete_and_null(&eigrp->topology_changes_externalIPV4); + list_delete_and_null(&eigrp->topology_changes_internalIPV4); + eigrp_delete(eigrp); XFREE(MTYPE_EIGRP_TOP, eigrp);