2 * EIGRP Sending and Receiving EIGRP Update Packets.
3 * Copyright (C) 2013-2016
15 * This file is part of GNU Zebra.
17 * GNU Zebra is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2, or (at your option) any
22 * GNU Zebra is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
27 * You should have received a copy of the GNU General Public License along
28 * with this program; see the file COPYING; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
40 #include "sockunion.h"
48 #include "plist_int.h"
52 #include "eigrpd/eigrp_structs.h"
53 #include "eigrpd/eigrpd.h"
54 #include "eigrpd/eigrp_interface.h"
55 #include "eigrpd/eigrp_neighbor.h"
56 #include "eigrpd/eigrp_packet.h"
57 #include "eigrpd/eigrp_zebra.h"
58 #include "eigrpd/eigrp_vty.h"
59 #include "eigrpd/eigrp_dump.h"
60 #include "eigrpd/eigrp_macros.h"
61 #include "eigrpd/eigrp_topology.h"
62 #include "eigrpd/eigrp_fsm.h"
63 #include "eigrpd/eigrp_network.h"
64 #include "eigrpd/eigrp_memory.h"
67 * @fn remove_received_prefix_gr
69 * @param[in] nbr_prefixes List of neighbor prefixes
70 * @param[in] recv_prefix Prefix which needs to be removed from list
75 * Function is used for removing received prefix
76 * from list of neighbor prefixes
79 remove_received_prefix_gr (struct list
*nbr_prefixes
, struct eigrp_prefix_entry
*recv_prefix
)
81 struct listnode
*node1
, *node11
;
82 struct eigrp_prefix_entry
*prefix
= NULL
;
84 /* iterate over all prefixes in list */
85 for (ALL_LIST_ELEMENTS(nbr_prefixes
, node1
, node11
, prefix
))
87 /* remove prefix from list if found */
88 if (prefix
== recv_prefix
)
90 listnode_delete(nbr_prefixes
, prefix
);
96 * @fn eigrp_update_receive_GR_ask
98 * @param[in] eigrp EIGRP process
99 * @param[in] nbr Neighbor update of who we received
100 * @param[in] nbr_prefixes Prefixes which weren't advertised
105 * Function is used for notifying FSM about prefixes which
106 * weren't advertised by neighbor:
107 * We will send message to FSM with prefix delay set to infinity.
110 eigrp_update_receive_GR_ask (struct eigrp
*eigrp
, struct eigrp_neighbor
*nbr
, struct list
*nbr_prefixes
)
112 struct listnode
*node1
;
113 struct eigrp_prefix_entry
*prefix
;
114 struct TLV_IPv4_Internal_type
*tlv_max
;
116 /* iterate over all prefixes which weren't advertised by neighbor */
117 for (ALL_LIST_ELEMENTS_RO(nbr_prefixes
, node1
, prefix
))
119 zlog_debug("GR receive: Neighbor not advertised %s/%d",
120 inet_ntoa(prefix
->destination_ipv4
->prefix
),
121 prefix
->destination_ipv4
->prefixlen
);
123 /* create internal IPv4 TLV with infinite delay */
124 tlv_max
= eigrp_IPv4_InternalTLV_new();
125 tlv_max
->type
= EIGRP_TLV_IPv4_INT
;
126 tlv_max
->length
= 28U;
127 tlv_max
->metric
= prefix
->reported_metric
;
128 /* set delay to MAX */
129 tlv_max
->metric
.delay
= EIGRP_MAX_METRIC
;
130 tlv_max
->destination
= prefix
->destination_ipv4
->prefix
;
131 tlv_max
->prefix_length
= prefix
->destination_ipv4
->prefixlen
;
134 /* prepare message for FSM */
135 struct eigrp_fsm_action_message
*fsm_msg
;
136 fsm_msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
137 sizeof(struct eigrp_fsm_action_message
));
139 struct eigrp_neighbor_entry
*entry
=
140 eigrp_prefix_entry_lookup(prefix
->entries
, nbr
);
142 fsm_msg
->packet_type
= EIGRP_OPC_UPDATE
;
143 fsm_msg
->eigrp
= eigrp
;
144 fsm_msg
->data_type
= EIGRP_TLV_IPv4_INT
;
145 fsm_msg
->adv_router
= nbr
;
146 fsm_msg
->data
.ipv4_int_type
= tlv_max
;
147 fsm_msg
->entry
= entry
;
148 fsm_msg
->prefix
= prefix
;
150 /* send message to FSM */
151 int event
= eigrp_get_fsm_event(fsm_msg
);
152 eigrp_fsm_event(fsm_msg
, event
);
154 /* free memory used by TLV */
155 eigrp_IPv4_InternalTLV_free (tlv_max
);
160 * EIGRP UPDATE read function
163 eigrp_update_receive (struct eigrp
*eigrp
, struct ip
*iph
, struct eigrp_header
*eigrph
,
164 struct stream
* s
, struct eigrp_interface
*ei
, int size
)
166 struct eigrp_neighbor
*nbr
;
167 struct TLV_IPv4_Internal_type
*tlv
;
168 struct eigrp_prefix_entry
*pe
;
169 struct eigrp_neighbor_entry
*ne
;
173 struct access_list
*alist
;
174 struct prefix_list
*plist
;
176 u_char graceful_restart
;
177 u_char graceful_restart_final
;
178 struct list
*nbr_prefixes
= NULL
;
180 /* increment statistics. */
183 /* get neighbor struct */
184 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
186 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
189 flags
= ntohl(eigrph
->flags
);
191 if (flags
& EIGRP_CR_FLAG
)
197 graceful_restart
= 0;
198 graceful_restart_final
= 0;
199 if((nbr
->recv_sequence_number
) == (ntohl(eigrph
->sequence
)))
202 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
203 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
204 zlog_debug("Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]",
205 size
, ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
),
207 nbr
->recv_sequence_number
, flags
);
210 if((flags
== (EIGRP_INIT_FLAG
+EIGRP_RS_FLAG
+EIGRP_EOT_FLAG
)) && (!same
))
212 /* Graceful restart Update received with all routes */
214 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
215 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
217 /* get all prefixes from neighbor from topology table */
218 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
219 graceful_restart
= 1;
220 graceful_restart_final
= 1;
222 else if((flags
== (EIGRP_INIT_FLAG
+EIGRP_RS_FLAG
)) && (!same
))
224 /* Graceful restart Update received, routes also in next packet */
226 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
227 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
229 /* get all prefixes from neighbor from topology table */
230 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
231 /* save prefixes to neighbor for later use */
232 nbr
->nbr_gr_prefixes
= nbr_prefixes
;
233 graceful_restart
= 1;
234 graceful_restart_final
= 0;
236 else if((flags
== (EIGRP_EOT_FLAG
)) && (!same
))
238 /* If there was INIT+RS Update packet before,
239 * consider this as GR EOT */
241 if(nbr
->nbr_gr_prefixes
!= NULL
)
243 /* this is final packet of GR */
244 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
245 nbr
->nbr_gr_prefixes
= NULL
;
247 graceful_restart
= 1;
248 graceful_restart_final
= 1;
252 else if((flags
== (0)) && (!same
))
254 /* If there was INIT+RS Update packet before,
255 * consider this as GR not final packet */
257 if(nbr
->nbr_gr_prefixes
!= NULL
)
259 /* this is GR not final route packet */
260 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
262 graceful_restart
= 1;
263 graceful_restart_final
= 0;
267 else if((flags
& EIGRP_INIT_FLAG
) && (!same
))
268 { /* When in pending state, send INIT update only if it wasn't
269 already sent before (only if init_sequence is 0) */
270 if((nbr
->state
== EIGRP_NEIGHBOR_PENDING
) && (nbr
->init_sequence_number
== 0))
271 eigrp_update_send_init(nbr
);
273 if (nbr
->state
== EIGRP_NEIGHBOR_UP
)
275 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
276 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
,nbr
);
277 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
278 zlog_info("Neighbor %s (%s) is down: peer restarted",
279 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
280 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_PENDING
);
281 zlog_info("Neighbor %s (%s) is pending: new adjacency",
282 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
283 eigrp_update_send_init(nbr
);
287 /*If there is topology information*/
288 while (s
->endp
> s
->getp
)
290 type
= stream_getw(s
);
291 if (type
== EIGRP_TLV_IPv4_INT
)
293 struct prefix_ipv4 dest_addr
;
295 stream_set_getp(s
, s
->getp
- sizeof(u_int16_t
));
297 tlv
= eigrp_read_ipv4_tlv(s
);
299 /*searching if destination exists */
300 dest_addr
.family
= AFI_IP
;
301 dest_addr
.prefix
= tlv
->destination
;
302 dest_addr
.prefixlen
= tlv
->prefix_length
;
303 struct eigrp_prefix_entry
*dest
=
304 eigrp_topology_table_lookup_ipv4(eigrp
->topology_table
, &dest_addr
);
306 /*if exists it comes to DUAL*/
309 /* remove received prefix from neighbor prefix list if in GR */
311 remove_received_prefix_gr(nbr_prefixes
, dest
);
313 struct eigrp_fsm_action_message
*msg
;
314 msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
315 sizeof(struct eigrp_fsm_action_message
));
316 struct eigrp_neighbor_entry
*entry
=
317 eigrp_prefix_entry_lookup(dest
->entries
, nbr
);
319 msg
->packet_type
= EIGRP_OPC_UPDATE
;
321 msg
->data_type
= EIGRP_TLV_IPv4_INT
;
322 msg
->adv_router
= nbr
;
323 msg
->data
.ipv4_int_type
= tlv
;
326 int event
= eigrp_get_fsm_event(msg
);
327 eigrp_fsm_event(msg
, event
);
331 /*Here comes topology information save*/
332 pe
= eigrp_prefix_entry_new();
333 pe
->serno
= eigrp
->serno
;
334 pe
->destination_ipv4
= prefix_ipv4_new();
335 prefix_copy((struct prefix
*)pe
->destination_ipv4
,
336 (struct prefix
*)&dest_addr
);
338 pe
->state
= EIGRP_FSM_STATE_PASSIVE
;
339 pe
->nt
= EIGRP_TOPOLOGY_TYPE_REMOTE
;
341 ne
= eigrp_neighbor_entry_new();
343 ne
->adv_router
= nbr
;
344 ne
->reported_metric
= tlv
->metric
;
345 ne
->reported_distance
=
346 eigrp_calculate_metrics(eigrp
,
353 * Check if there is any access-list on interface (IN direction)
354 * and set distance to max
356 alist
= ei
->list
[EIGRP_FILTER_IN
];
358 /* Check if access-list fits */
360 access_list_apply (alist
, (struct prefix
*)&dest_addr
) == FILTER_DENY
)
362 /* If yes, set reported metric to Max */
363 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
365 ne
->distance
= eigrp_calculate_total_metrics(eigrp
, ne
);
368 plist
= e
->prefix
[EIGRP_FILTER_IN
];
370 /* Check if prefix-list fits */
372 prefix_list_apply (plist
, (struct prefix
*)&dest_addr
) == PREFIX_DENY
)
374 /* If yes, set reported metric to Max */
375 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
378 /*Get access-list from current interface */
379 alist
= ei
->list
[EIGRP_FILTER_IN
];
381 /* Check if access-list fits */
383 access_list_apply (alist
, (struct prefix
*)&dest_addr
) == FILTER_DENY
)
385 /* If yes, set reported metric to Max */
386 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
389 plist
= ei
->prefix
[EIGRP_FILTER_IN
];
391 /* Check if prefix-list fits */
393 prefix_list_apply (plist
, (struct prefix
*)&dest_addr
) == PREFIX_DENY
)
395 /* If yes, set reported metric to Max */
396 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
402 ne
->distance
= eigrp_calculate_total_metrics(eigrp
, ne
);
404 pe
->fdistance
= pe
->distance
= pe
->rdistance
=
407 ne
->flags
= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG
;
409 eigrp_prefix_entry_add(eigrp
->topology_table
, pe
);
410 eigrp_neighbor_entry_add(pe
, ne
);
411 pe
->distance
= pe
->fdistance
= pe
->rdistance
=
413 pe
->reported_metric
= ne
->total_metric
;
414 eigrp_topology_update_node_flags(pe
);
416 pe
->req_action
|= EIGRP_FSM_NEED_UPDATE
;
417 listnode_add(eigrp
->topology_changes_internalIPV4
, pe
);
419 eigrp_IPv4_InternalTLV_free (tlv
);
423 /* ask about prefixes not present in GR update,
424 * if this is final GR packet */
425 if(graceful_restart_final
)
427 eigrp_update_receive_GR_ask(eigrp
, nbr
, nbr_prefixes
);
431 * We don't need to send separate Ack for INIT Update. INIT will be acked in EOT Update.
433 if ((nbr
->state
== EIGRP_NEIGHBOR_UP
) && !(flags
== EIGRP_INIT_FLAG
))
435 eigrp_hello_send_ack(nbr
);
438 eigrp_query_send_all(eigrp
);
439 eigrp_update_send_all(eigrp
, ei
);
442 /*send EIGRP Update packet*/
444 eigrp_update_send_init (struct eigrp_neighbor
*nbr
)
446 struct eigrp_packet
*ep
;
447 u_int16_t length
= EIGRP_HEADER_LEN
;
449 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
451 /* Prepare EIGRP INIT UPDATE header */
452 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
453 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
454 nbr
->ei
->eigrp
->sequence_number
,
455 nbr
->recv_sequence_number
);
457 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
, EIGRP_INIT_FLAG
,
458 nbr
->ei
->eigrp
->sequence_number
,
459 nbr
->recv_sequence_number
);
461 // encode Authentication TLV, if needed
462 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
463 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
465 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,nbr
->ei
);
466 eigrp_make_md5_digest(nbr
->ei
,ep
->s
, EIGRP_AUTH_UPDATE_INIT_FLAG
);
470 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
473 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
475 /*This ack number we await from neighbor*/
476 nbr
->init_sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
477 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
478 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
479 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
480 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
482 /*Put packet to retransmission queue*/
483 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
485 if (nbr
->retrans_queue
->count
== 1)
487 eigrp_send_packet_reliably(nbr
);
492 eigrp_update_send_EOT (struct eigrp_neighbor
*nbr
)
494 struct eigrp_packet
*ep
;
495 // struct eigrp_packet *ep_multicast;
496 u_int16_t length
= EIGRP_HEADER_LEN
;
497 struct eigrp_neighbor_entry
*te
;
498 struct eigrp_prefix_entry
*pe
;
499 struct listnode
*node
, *node2
, *nnode
, *nnode2
;
500 struct access_list
*alist
;
501 struct prefix_list
*plist
;
502 struct access_list
*alist_i
;
503 struct prefix_list
*plist_i
;
505 struct prefix_ipv4
*dest_addr
;
507 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
509 /* Prepare EIGRP EOT UPDATE header */
510 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
, EIGRP_EOT_FLAG
,
511 nbr
->ei
->eigrp
->sequence_number
,
512 nbr
->recv_sequence_number
);
514 // encode Authentication TLV, if needed
515 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) && (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
517 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,nbr
->ei
);
520 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node
, nnode
, pe
))
522 for (ALL_LIST_ELEMENTS(pe
->entries
, node2
, nnode2
, te
))
524 if ((te
->ei
== nbr
->ei
)
525 && (te
->prefix
->nt
== EIGRP_TOPOLOGY_TYPE_REMOTE
))
528 /* Get destination address from prefix */
529 dest_addr
= pe
->destination_ipv4
;
534 //TODO: Work in progress
535 /* get list from eigrp process */
537 /* Get access-lists and prefix-lists from process and interface */
538 alist
= e
->list
[EIGRP_FILTER_OUT
];
539 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
540 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_OUT
];
541 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_OUT
];
543 /* Check if any list fits */
544 if ((alist
&& access_list_apply (alist
,
545 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
546 (plist
&& prefix_list_apply (plist
,
547 (struct prefix
*) dest_addr
) == PREFIX_DENY
)||
548 (alist_i
&& access_list_apply (alist_i
,
549 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
550 (plist_i
&& prefix_list_apply (plist_i
,
551 (struct prefix
*) dest_addr
) == PREFIX_DENY
))
553 zlog_info("PROC OUT EOT: Skipping");
554 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
555 zlog_info("PROC OUT EOT Prefix: %s", inet_ntoa(dest_addr
->prefix
));
558 zlog_info("PROC OUT EOT: NENastavujem metriku ");
559 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
565 /* NULL the pointer */
571 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
572 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
574 eigrp_make_md5_digest(nbr
->ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
578 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
581 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
583 /*This ack number we await from neighbor*/
584 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
586 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
587 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
588 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
590 /*Put packet to retransmission queue*/
591 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
593 if (nbr
->retrans_queue
->count
== 1)
595 eigrp_send_packet_reliably(nbr
);
600 eigrp_update_send (struct eigrp_interface
*ei
)
602 struct eigrp_packet
*ep
;
603 struct listnode
*node
, *nnode
;
604 struct eigrp_neighbor
*nbr
;
605 struct eigrp_prefix_entry
*pe
;
607 struct access_list
*alist
;
608 struct prefix_list
*plist
;
609 struct access_list
*alist_i
;
610 struct prefix_list
*plist_i
;
612 struct prefix_ipv4
*dest_addr
;
613 bool packet_sent
= false;
615 u_int16_t length
= EIGRP_HEADER_LEN
;
617 ep
= eigrp_packet_new(ei
->ifp
->mtu
);
619 /* Prepare EIGRP INIT UPDATE header */
620 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, ei
, ep
->s
, 0,
621 ei
->eigrp
->sequence_number
, 0);
623 // encode Authentication TLV, if needed
624 if((IF_DEF_PARAMS (ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
625 (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
627 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,ei
);
631 for (ALL_LIST_ELEMENTS(ei
->eigrp
->topology_changes_internalIPV4
, node
, nnode
, pe
))
633 if(pe
->req_action
& EIGRP_FSM_NEED_UPDATE
)
635 /* Get destination address from prefix */
636 dest_addr
= pe
->destination_ipv4
;
641 //TODO: Work in progress
642 /* get list from eigrp process */
644 /* Get access-lists and prefix-lists from process and interface */
645 alist
= e
->list
[EIGRP_FILTER_OUT
];
646 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
647 alist_i
= ei
->list
[EIGRP_FILTER_OUT
];
648 plist_i
= ei
->prefix
[EIGRP_FILTER_OUT
];
650 /* Check if any list fits */
651 if ((alist
&& access_list_apply (alist
,
652 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
653 (plist
&& prefix_list_apply (plist
,
654 (struct prefix
*) dest_addr
) == PREFIX_DENY
)||
655 (alist_i
&& access_list_apply (alist_i
,
656 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
657 (plist_i
&& prefix_list_apply (plist_i
,
658 (struct prefix
*) dest_addr
) == PREFIX_DENY
))
660 zlog_info("PROC OUT: Skipping");
661 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
662 zlog_info("PROC OUT Prefix: %s", inet_ntoa(dest_addr
->prefix
));
665 zlog_info("PROC OUT: NENastavujem metriku ");
666 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
673 /* NULL the pointer */
681 eigrp_packet_free(ep
);
685 if((IF_DEF_PARAMS (ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
)
686 && (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
688 eigrp_make_md5_digest(ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
692 eigrp_packet_checksum(ei
, ep
->s
, length
);
695 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
697 /*This ack number we await from neighbor*/
698 ep
->sequence_number
= ei
->eigrp
->sequence_number
;
700 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
701 zlog_debug("Enqueuing Update length[%u] Seq [%u]",
702 length
, ep
->sequence_number
);
704 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node
, nnode
, nbr
))
706 if (nbr
->state
== EIGRP_NEIGHBOR_UP
)
709 /*Put packet to retransmission queue*/
710 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
712 if (nbr
->retrans_queue
->count
== 1)
714 eigrp_send_packet_reliably(nbr
);
720 eigrp_packet_free(ep
);
724 eigrp_update_send_all (struct eigrp
*eigrp
, struct eigrp_interface
*exception
)
726 struct eigrp_interface
*iface
;
727 struct listnode
*node
, *node2
, *nnode2
;
728 struct eigrp_prefix_entry
*pe
;
730 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
))
732 if (iface
!= exception
)
734 eigrp_update_send(iface
);
738 for (ALL_LIST_ELEMENTS(eigrp
->topology_changes_internalIPV4
, node2
, nnode2
, pe
))
740 if(pe
->req_action
& EIGRP_FSM_NEED_UPDATE
)
742 pe
->req_action
&= ~EIGRP_FSM_NEED_UPDATE
;
743 listnode_delete(eigrp
->topology_changes_internalIPV4
, pe
);
744 zlog_debug("UPDATE COUNT: %d", eigrp
->topology_changes_internalIPV4
->count
);
750 * @fn eigrp_update_send_GR_part
752 * @param[in] nbr contains neighbor who would receive Graceful restart
757 * Function used for sending Graceful restart Update packet
758 * and if there are multiple chunks, send only one of them.
759 * It is called from thread. Do not call it directly.
761 * Uses nbr_gr_packet_type from neighbor.
764 eigrp_update_send_GR_part(struct eigrp_neighbor
*nbr
)
766 struct eigrp_packet
*ep
;
767 u_int16_t length
= EIGRP_HEADER_LEN
;
768 struct listnode
*node
, *nnode
;
769 struct eigrp_prefix_entry
*pe
;
770 struct prefix_ipv4
*dest_addr
;
772 struct access_list
*alist
, *alist_i
;
773 struct prefix_list
*plist
, *plist_i
;
774 struct list
*prefixes
;
776 unsigned int send_prefixes
;
777 struct TLV_IPv4_Internal_type
*tlv_max
;
779 /* get prefixes to send to neighbor */
780 prefixes
= nbr
->nbr_gr_prefixes_send
;
783 length
= EIGRP_HEADER_LEN
;
785 /* if there already were last packet chunk, we won't continue */
786 if(nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_LAST
)
789 /* if this is first packet chunk, we need to decide,
790 * if there will be one or more chunks */
791 if(nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_FIRST
)
793 if(prefixes
->count
<= EIGRP_TLV_MAX_IPv4
)
795 /* there will be only one chunk */
796 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
+ EIGRP_EOT_FLAG
;
797 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
801 /* there will be more chunks */
802 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
;
803 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
808 /* this is not first chunk, and we need to decide,
809 * if there will be more chunks */
810 if(prefixes
->count
<= EIGRP_TLV_MAX_IPv4
)
812 /* this is last chunk */
813 flags
= EIGRP_EOT_FLAG
;
814 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
818 /* there will be more chunks */
820 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
824 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
826 /* Prepare EIGRP Graceful restart UPDATE header */
827 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
,
829 nbr
->ei
->eigrp
->sequence_number
,
830 nbr
->recv_sequence_number
);
832 // encode Authentication TLV, if needed
833 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
834 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
836 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,nbr
->ei
);
839 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node
, nnode
, pe
))
844 dest_addr
= pe
->destination_ipv4
;
845 /* get list from eigrp process */
847 /* Get access-lists and prefix-lists from process and interface */
848 alist
= e
->list
[EIGRP_FILTER_OUT
];
849 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
850 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_OUT
];
851 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_OUT
];
853 /* Check if any list fits */
854 if ((alist
&& access_list_apply (alist
,
855 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
856 (plist
&& prefix_list_apply (plist
,
857 (struct prefix
*) dest_addr
) == PREFIX_DENY
)||
858 (alist_i
&& access_list_apply (alist_i
,
859 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
860 (plist_i
&& prefix_list_apply (plist_i
,
861 (struct prefix
*) dest_addr
) == PREFIX_DENY
))
863 /* do not send filtered route */
864 zlog_info("Filtered prefix %s won't be sent out.",
865 inet_ntoa(dest_addr
->prefix
));
869 /* sending route which wasn't filtered */
870 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
874 alist
= e
->list
[EIGRP_FILTER_IN
];
875 plist
= e
->prefix
[EIGRP_FILTER_IN
];
876 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_IN
];
877 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_IN
];
879 /* Check if any list fits */
880 if ((alist
&& access_list_apply (alist
,
881 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
882 (plist
&& prefix_list_apply (plist
,
883 (struct prefix
*) dest_addr
) == PREFIX_DENY
)||
884 (alist_i
&& access_list_apply (alist_i
,
885 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
886 (plist_i
&& prefix_list_apply (plist_i
,
887 (struct prefix
*) dest_addr
) == PREFIX_DENY
))
889 /* do not send filtered route */
890 zlog_info("Filtered prefix %s will be removed.",
891 inet_ntoa(dest_addr
->prefix
));
893 tlv_max
= eigrp_IPv4_InternalTLV_new();
894 tlv_max
->type
= EIGRP_TLV_IPv4_INT
;
895 tlv_max
->length
= 28U;
896 tlv_max
->metric
= pe
->reported_metric
;
897 /* set delay to MAX */
898 tlv_max
->metric
.delay
= EIGRP_MAX_METRIC
;
899 tlv_max
->destination
= pe
->destination_ipv4
->prefix
;
900 tlv_max
->prefix_length
= pe
->destination_ipv4
->prefixlen
;
902 /* prepare message for FSM */
903 struct eigrp_fsm_action_message
*fsm_msg
;
904 fsm_msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
905 sizeof(struct eigrp_fsm_action_message
));
907 struct eigrp_neighbor_entry
*entry
=
908 eigrp_prefix_entry_lookup(pe
->entries
, nbr
);
910 fsm_msg
->packet_type
= EIGRP_OPC_UPDATE
;
912 fsm_msg
->data_type
= EIGRP_TLV_IPv4_INT
;
913 fsm_msg
->adv_router
= nbr
;
914 fsm_msg
->data
.ipv4_int_type
= tlv_max
;
915 fsm_msg
->entry
= entry
;
916 fsm_msg
->prefix
= pe
;
918 /* send message to FSM */
919 int event
= eigrp_get_fsm_event(fsm_msg
);
920 eigrp_fsm_event(fsm_msg
, event
);
922 /* free memory used by TLV */
923 eigrp_IPv4_InternalTLV_free (tlv_max
);
929 /* NULL the pointer */
932 /* delete processed prefix from list */
933 listnode_delete(prefixes
, pe
);
935 /* if there are enough prefixes, send packet */
936 if(send_prefixes
>= EIGRP_TLV_MAX_IPv4
)
940 /* compute Auth digest */
941 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
942 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
944 eigrp_make_md5_digest(nbr
->ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
948 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
951 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
953 /*This ack number we await from neighbor*/
954 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
956 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
957 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
958 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
960 /*Put packet to retransmission queue*/
961 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
963 if (nbr
->retrans_queue
->count
== 1)
965 eigrp_send_packet_reliably(nbr
);
970 * @fn eigrp_update_send_GR_thread
972 * @param[in] thread contains neighbor who would receive Graceful restart
974 * @return int always 0
977 * Function used for sending Graceful restart Update packet
978 * in thread, it is prepared for multiple chunks of packet.
980 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
983 eigrp_update_send_GR_thread(struct thread
*thread
)
985 struct eigrp_neighbor
*nbr
;
987 /* get argument from thread */
988 nbr
= THREAD_ARG(thread
);
989 /* remove this thread pointer */
990 nbr
->t_nbr_send_gr
= NULL
;
992 /* if there is packet waiting in queue,
993 * schedule this thread again with small delay */
994 if(nbr
->retrans_queue
->count
> 0)
996 nbr
->t_nbr_send_gr
= NULL
;
997 thread_add_timer_msec(master
, eigrp_update_send_GR_thread
, nbr
, 10,
998 &nbr
->t_nbr_send_gr
);
1002 /* send GR EIGRP packet chunk */
1003 eigrp_update_send_GR_part(nbr
);
1005 /* if it wasn't last chunk, schedule this thread again */
1006 if(nbr
->nbr_gr_packet_type
!= EIGRP_PACKET_PART_LAST
) {
1007 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
1008 nbr
->t_nbr_send_gr
= NULL
;
1015 * @fn eigrp_update_send_GR
1017 * @param[in] nbr Neighbor who would receive Graceful restart
1018 * @param[in] gr_type Who executed Graceful restart
1019 * @param[in] vty Virtual terminal for log output
1024 * Function used for sending Graceful restart Update packet:
1025 * Creates Update packet with INIT, RS, EOT flags and include
1026 * all route except those filtered
1029 eigrp_update_send_GR (struct eigrp_neighbor
*nbr
, enum GR_type gr_type
, struct vty
*vty
)
1031 struct eigrp_prefix_entry
*pe2
;
1032 struct listnode
*node2
, *nnode2
;
1033 struct list
*prefixes
;
1035 if(gr_type
== EIGRP_GR_FILTER
)
1037 /* function was called after applying filtration */
1038 zlog_info("Neighbor %s (%s) is resync: route configuration changed",
1039 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
1041 else if(gr_type
== EIGRP_GR_MANUAL
)
1043 /* Graceful restart was called manually */
1044 zlog_info("Neighbor %s (%s) is resync: manually cleared",
1045 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
1049 vty_time_print (vty
, 0);
1050 vty_out (vty
, "Neighbor %s (%s) is resync: manually cleared%s",
1051 inet_ntoa (nbr
->src
),
1052 ifindex2ifname (nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
),
1057 prefixes
= list_new();
1058 /* add all prefixes from topology table to list */
1059 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node2
, nnode2
, pe2
))
1061 listnode_add(prefixes
, pe2
);
1064 /* save prefixes to neighbor */
1065 nbr
->nbr_gr_prefixes_send
= prefixes
;
1066 /* indicate, that this is first GR Update packet chunk */
1067 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_FIRST
;
1068 /* execute packet sending in thread */
1069 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
1070 nbr
->t_nbr_send_gr
= NULL
;
1074 * @fn eigrp_update_send_interface_GR
1076 * @param[in] ei Interface to neighbors of which the GR is sent
1077 * @param[in] gr_type Who executed Graceful restart
1078 * @param[in] vty Virtual terminal for log output
1083 * Function used for sending Graceful restart Update packet
1084 * to all neighbors on specified interface.
1087 eigrp_update_send_interface_GR (struct eigrp_interface
*ei
, enum GR_type gr_type
, struct vty
*vty
)
1089 struct listnode
*node
;
1090 struct eigrp_neighbor
*nbr
;
1092 /* iterate over all neighbors on eigrp interface */
1093 for (ALL_LIST_ELEMENTS_RO(ei
->nbrs
, node
, nbr
))
1095 /* send GR to neighbor */
1096 eigrp_update_send_GR(nbr
, gr_type
, vty
);
1101 * @fn eigrp_update_send_process_GR
1103 * @param[in] eigrp EIGRP process
1104 * @param[in] gr_type Who executed Graceful restart
1105 * @param[in] vty Virtual terminal for log output
1110 * Function used for sending Graceful restart Update packet
1111 * to all neighbors in eigrp process.
1114 eigrp_update_send_process_GR (struct eigrp
*eigrp
, enum GR_type gr_type
, struct vty
*vty
)
1116 struct listnode
*node
;
1117 struct eigrp_interface
*ei
;
1119 /* iterate over all eigrp interfaces */
1120 for (ALL_LIST_ELEMENTS_RO (eigrp
->eiflist
, node
, ei
))
1122 /* send GR to all neighbors on interface */
1123 eigrp_update_send_interface_GR(ei
, gr_type
, vty
);