Merge pull request #1382 from donaldsharp/eigrp_loop

Eigrp loop
This commit is contained in:
Russ White 2017-10-31 20:21:26 -04:00 committed by GitHub
commit 58239911bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 199 additions and 65 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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);