1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * EIGRP Sending and Receiving EIGRP Update Packets.
4 * Copyright (C) 2013-2016
25 #include "sockunion.h"
33 #include "plist_int.h"
37 #include "eigrpd/eigrp_types.h"
38 #include "eigrpd/eigrp_structs.h"
39 #include "eigrpd/eigrpd.h"
40 #include "eigrpd/eigrp_interface.h"
41 #include "eigrpd/eigrp_neighbor.h"
42 #include "eigrpd/eigrp_packet.h"
43 #include "eigrpd/eigrp_zebra.h"
44 #include "eigrpd/eigrp_vty.h"
45 #include "eigrpd/eigrp_dump.h"
46 #include "eigrpd/eigrp_macros.h"
47 #include "eigrpd/eigrp_topology.h"
48 #include "eigrpd/eigrp_fsm.h"
49 #include "eigrpd/eigrp_network.h"
50 #include "eigrpd/eigrp_metric.h"
52 bool eigrp_update_prefix_apply(struct eigrp
*eigrp
, struct eigrp_interface
*ei
,
53 int in
, struct prefix
*prefix
)
55 struct access_list
*alist
;
56 struct prefix_list
*plist
;
58 alist
= eigrp
->list
[in
];
59 if (alist
&& access_list_apply(alist
, prefix
) == FILTER_DENY
)
62 plist
= eigrp
->prefix
[in
];
63 if (plist
&& prefix_list_apply(plist
, prefix
) == PREFIX_DENY
)
67 if (alist
&& access_list_apply(alist
, prefix
) == FILTER_DENY
)
70 plist
= ei
->prefix
[in
];
71 if (plist
&& prefix_list_apply(plist
, prefix
) == PREFIX_DENY
)
78 * @fn remove_received_prefix_gr
80 * @param[in] nbr_prefixes List of neighbor prefixes
81 * @param[in] recv_prefix Prefix which needs to be removed from
87 * Function is used for removing received prefix
88 * from list of neighbor prefixes
91 remove_received_prefix_gr(struct list
*nbr_prefixes
,
92 struct eigrp_prefix_descriptor
*recv_prefix
)
94 struct listnode
*node1
, *node11
;
95 struct eigrp_prefix_descriptor
*prefix
= NULL
;
97 /* iterate over all prefixes in list */
98 for (ALL_LIST_ELEMENTS(nbr_prefixes
, node1
, node11
, prefix
)) {
99 /* remove prefix from list if found */
100 if (prefix
== recv_prefix
) {
101 listnode_delete(nbr_prefixes
, prefix
);
107 * @fn eigrp_update_receive_GR_ask
109 * @param[in] eigrp EIGRP process
110 * @param[in] nbr Neighbor update of who we
112 * @param[in] nbr_prefixes Prefixes which weren't advertised
117 * Function is used for notifying FSM about prefixes which
118 * weren't advertised by neighbor:
119 * We will send message to FSM with prefix delay set to infinity.
121 static void eigrp_update_receive_GR_ask(struct eigrp
*eigrp
,
122 struct eigrp_neighbor
*nbr
,
123 struct list
*nbr_prefixes
)
125 struct listnode
*node1
;
126 struct eigrp_prefix_descriptor
*prefix
;
127 struct eigrp_fsm_action_message fsm_msg
;
129 /* iterate over all prefixes which weren't advertised by neighbor */
130 for (ALL_LIST_ELEMENTS_RO(nbr_prefixes
, node1
, prefix
)) {
131 zlog_debug("GR receive: Neighbor not advertised %pFX",
132 prefix
->destination
);
134 fsm_msg
.metrics
= prefix
->reported_metric
;
135 /* set delay to MAX */
136 fsm_msg
.metrics
.delay
= EIGRP_MAX_METRIC
;
138 struct eigrp_route_descriptor
*entry
=
139 eigrp_route_descriptor_lookup(prefix
->entries
, nbr
);
141 fsm_msg
.packet_type
= EIGRP_OPC_UPDATE
;
142 fsm_msg
.eigrp
= eigrp
;
143 fsm_msg
.data_type
= EIGRP_INT
;
144 fsm_msg
.adv_router
= nbr
;
145 fsm_msg
.entry
= entry
;
146 fsm_msg
.prefix
= prefix
;
148 /* send message to FSM */
149 eigrp_fsm_event(&fsm_msg
);
154 * EIGRP UPDATE read function
156 void eigrp_update_receive(struct eigrp
*eigrp
, struct ip
*iph
,
157 struct eigrp_header
*eigrph
, struct stream
*s
,
158 struct eigrp_interface
*ei
, int size
)
160 struct eigrp_neighbor
*nbr
;
161 struct TLV_IPv4_Internal_type
*tlv
;
162 struct eigrp_prefix_descriptor
*pe
;
163 struct eigrp_route_descriptor
*ne
;
168 struct prefix dest_addr
;
169 uint8_t graceful_restart
;
170 uint8_t graceful_restart_final
;
171 struct list
*nbr_prefixes
= NULL
;
173 /* increment statistics. */
176 /* get neighbor struct */
177 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
179 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
182 flags
= ntohl(eigrph
->flags
);
184 if (flags
& EIGRP_CR_FLAG
) {
189 graceful_restart
= 0;
190 graceful_restart_final
= 0;
191 if ((nbr
->recv_sequence_number
) == (ntohl(eigrph
->sequence
)))
194 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
195 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
197 "Processing Update size[%u] int(%s) nbr(%pI4) seq [%u] flags [%0x]",
199 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, eigrp
->vrf_id
),
200 &nbr
->src
, nbr
->recv_sequence_number
, flags
);
203 if ((flags
== (EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
+ EIGRP_EOT_FLAG
))
205 /* Graceful restart Update received with all routes */
207 zlog_info("Neighbor %pI4 (%s) is resync: peer graceful-restart",
209 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, eigrp
->vrf_id
));
211 /* get all prefixes from neighbor from topology table */
212 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
213 graceful_restart
= 1;
214 graceful_restart_final
= 1;
215 } else if ((flags
== (EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
)) && (!same
)) {
216 /* Graceful restart Update received, routes also in next packet
219 zlog_info("Neighbor %pI4 (%s) is resync: peer graceful-restart",
221 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, eigrp
->vrf_id
));
223 /* get all prefixes from neighbor from topology table */
224 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
225 /* save prefixes to neighbor for later use */
226 nbr
->nbr_gr_prefixes
= nbr_prefixes
;
227 graceful_restart
= 1;
228 graceful_restart_final
= 0;
229 } else if ((flags
== (EIGRP_EOT_FLAG
)) && (!same
)) {
230 /* If there was INIT+RS Update packet before,
231 * consider this as GR EOT */
233 if (nbr
->nbr_gr_prefixes
!= NULL
) {
234 /* this is final packet of GR */
235 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
236 nbr
->nbr_gr_prefixes
= NULL
;
238 graceful_restart
= 1;
239 graceful_restart_final
= 1;
242 } else if ((flags
== (0)) && (!same
)) {
243 /* If there was INIT+RS Update packet before,
244 * consider this as GR not final packet */
246 if (nbr
->nbr_gr_prefixes
!= NULL
) {
247 /* this is GR not final route packet */
248 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
250 graceful_restart
= 1;
251 graceful_restart_final
= 0;
254 } else if ((flags
& EIGRP_INIT_FLAG
)
255 && (!same
)) { /* When in pending state, send INIT update only
257 already sent before (only if init_sequence
259 if ((nbr
->state
== EIGRP_NEIGHBOR_PENDING
)
260 && (nbr
->init_sequence_number
== 0))
261 eigrp_update_send_init(nbr
);
263 if (nbr
->state
== EIGRP_NEIGHBOR_UP
) {
264 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
265 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
, nbr
);
266 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
267 zlog_info("Neighbor %pI4 (%s) is down: peer restarted",
269 ifindex2ifname(nbr
->ei
->ifp
->ifindex
,
271 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_PENDING
);
273 "Neighbor %pI4 (%s) is pending: new adjacency",
275 ifindex2ifname(nbr
->ei
->ifp
->ifindex
,
277 eigrp_update_send_init(nbr
);
281 /*If there is topology information*/
282 while (s
->endp
> s
->getp
) {
283 type
= stream_getw(s
);
285 case EIGRP_TLV_IPv4_INT
:
286 stream_set_getp(s
, s
->getp
- sizeof(uint16_t));
288 tlv
= eigrp_read_ipv4_tlv(s
);
290 /*searching if destination exists */
291 dest_addr
.family
= AF_INET
;
292 dest_addr
.u
.prefix4
= tlv
->destination
;
293 dest_addr
.prefixlen
= tlv
->prefix_length
;
294 struct eigrp_prefix_descriptor
*dest
=
295 eigrp_topology_table_lookup_ipv4(
296 eigrp
->topology_table
, &dest_addr
);
298 /*if exists it comes to DUAL*/
300 /* remove received prefix from neighbor prefix
302 if (graceful_restart
)
303 remove_received_prefix_gr(nbr_prefixes
,
306 struct eigrp_fsm_action_message msg
;
307 struct eigrp_route_descriptor
*entry
=
308 eigrp_route_descriptor_lookup(
311 msg
.packet_type
= EIGRP_OPC_UPDATE
;
313 msg
.data_type
= EIGRP_INT
;
314 msg
.adv_router
= nbr
;
315 msg
.metrics
= tlv
->metric
;
318 eigrp_fsm_event(&msg
);
320 /*Here comes topology information save*/
321 pe
= eigrp_prefix_descriptor_new();
322 pe
->serno
= eigrp
->serno
;
324 (struct prefix
*)prefix_ipv4_new();
325 prefix_copy(pe
->destination
, &dest_addr
);
327 pe
->state
= EIGRP_FSM_STATE_PASSIVE
;
328 pe
->nt
= EIGRP_TOPOLOGY_TYPE_REMOTE
;
330 ne
= eigrp_route_descriptor_new();
332 ne
->adv_router
= nbr
;
333 ne
->reported_metric
= tlv
->metric
;
334 ne
->reported_distance
= eigrp_calculate_metrics(
339 if (eigrp_update_prefix_apply(eigrp
, ei
,
342 ne
->reported_metric
.delay
=
345 ne
->distance
= eigrp_calculate_total_metrics(
348 pe
->fdistance
= pe
->distance
= pe
->rdistance
=
352 EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG
;
354 eigrp_prefix_descriptor_add(
355 eigrp
->topology_table
, pe
);
356 eigrp_route_descriptor_add(eigrp
, pe
, ne
);
357 pe
->distance
= pe
->fdistance
= pe
->rdistance
=
359 pe
->reported_metric
= ne
->total_metric
;
360 eigrp_topology_update_node_flags(eigrp
, pe
);
362 pe
->req_action
|= EIGRP_FSM_NEED_UPDATE
;
364 eigrp
->topology_changes_internalIPV4
,
367 eigrp_IPv4_InternalTLV_free(tlv
);
370 case EIGRP_TLV_IPv4_EXT
:
371 /* DVS: processing of external routes needs packet and fsm work.
372 * for now, lets just not creash the box
375 length
= stream_getw(s
);
376 // -2 for type, -2 for len
377 for (length
-= 4; length
; length
--) {
378 (void)stream_getc(s
);
383 /* ask about prefixes not present in GR update,
384 * if this is final GR packet */
385 if (graceful_restart_final
) {
386 eigrp_update_receive_GR_ask(eigrp
, nbr
, nbr_prefixes
);
390 * We don't need to send separate Ack for INIT Update. INIT will be
391 * acked in EOT Update.
393 if ((nbr
->state
== EIGRP_NEIGHBOR_UP
) && !(flags
== EIGRP_INIT_FLAG
)) {
394 eigrp_hello_send_ack(nbr
);
397 eigrp_query_send_all(eigrp
);
398 eigrp_update_send_all(eigrp
, ei
);
401 list_delete(&nbr_prefixes
);
404 /*send EIGRP Update packet*/
405 void eigrp_update_send_init(struct eigrp_neighbor
*nbr
)
407 struct eigrp_packet
*ep
;
408 uint16_t length
= EIGRP_HEADER_LEN
;
410 ep
= eigrp_packet_new(EIGRP_PACKET_MTU(nbr
->ei
->ifp
->mtu
), nbr
);
412 /* Prepare EIGRP INIT UPDATE header */
413 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
414 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
415 nbr
->ei
->eigrp
->sequence_number
,
416 nbr
->recv_sequence_number
);
418 eigrp_packet_header_init(
419 EIGRP_OPC_UPDATE
, nbr
->ei
->eigrp
, ep
->s
, EIGRP_INIT_FLAG
,
420 nbr
->ei
->eigrp
->sequence_number
, nbr
->recv_sequence_number
);
422 // encode Authentication TLV, if needed
423 if ((nbr
->ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
424 && (nbr
->ei
->params
.auth_keychain
!= NULL
)) {
425 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, nbr
->ei
);
426 eigrp_make_md5_digest(nbr
->ei
, ep
->s
,
427 EIGRP_AUTH_UPDATE_INIT_FLAG
);
431 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
434 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
436 /*This ack number we await from neighbor*/
437 nbr
->init_sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
438 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
439 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
441 "Enqueuing Update Init Len [%u] Seq [%u] Dest [%pI4]",
442 ep
->length
, ep
->sequence_number
, &ep
->dst
);
444 /*Put packet to retransmission queue*/
445 eigrp_fifo_push(nbr
->retrans_queue
, ep
);
447 if (nbr
->retrans_queue
->count
== 1) {
448 eigrp_send_packet_reliably(nbr
);
452 static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor
*nbr
,
453 struct eigrp_packet
*ep
,
454 uint32_t seq_no
, int length
)
456 if ((nbr
->ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
457 && (nbr
->ei
->params
.auth_keychain
!= NULL
)) {
458 eigrp_make_md5_digest(nbr
->ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
462 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
465 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
467 /*This ack number we await from neighbor*/
468 ep
->sequence_number
= seq_no
;
470 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
472 "Enqueuing Update Init Len [%u] Seq [%u] Dest [%pI4]",
473 ep
->length
, ep
->sequence_number
, &ep
->dst
);
475 /*Put packet to retransmission queue*/
476 eigrp_fifo_push(nbr
->retrans_queue
, ep
);
478 if (nbr
->retrans_queue
->count
== 1)
479 eigrp_send_packet_reliably(nbr
);
482 static void eigrp_update_send_to_all_nbrs(struct eigrp_interface
*ei
,
483 struct eigrp_packet
*ep
)
485 struct listnode
*node
, *nnode
;
486 struct eigrp_neighbor
*nbr
;
487 bool packet_sent
= false;
489 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node
, nnode
, nbr
)) {
490 struct eigrp_packet
*ep_dup
;
492 if (nbr
->state
!= EIGRP_NEIGHBOR_UP
)
496 ep_dup
= eigrp_packet_duplicate(ep
, NULL
);
502 /*Put packet to retransmission queue*/
503 eigrp_fifo_push(nbr
->retrans_queue
, ep_dup
);
505 if (nbr
->retrans_queue
->count
== 1) {
506 eigrp_send_packet_reliably(nbr
);
511 eigrp_packet_free(ep
);
514 void eigrp_update_send_EOT(struct eigrp_neighbor
*nbr
)
516 struct eigrp_packet
*ep
;
517 uint16_t length
= EIGRP_HEADER_LEN
;
518 struct eigrp_route_descriptor
*te
;
519 struct eigrp_prefix_descriptor
*pe
;
520 struct listnode
*node2
, *nnode2
;
521 struct eigrp_interface
*ei
= nbr
->ei
;
522 struct eigrp
*eigrp
= ei
->eigrp
;
523 struct prefix
*dest_addr
;
524 uint32_t seq_no
= eigrp
->sequence_number
;
525 uint16_t eigrp_mtu
= EIGRP_PACKET_MTU(ei
->ifp
->mtu
);
526 struct route_node
*rn
;
528 ep
= eigrp_packet_new(eigrp_mtu
, nbr
);
530 /* Prepare EIGRP EOT UPDATE header */
531 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
, EIGRP_EOT_FLAG
,
532 seq_no
, nbr
->recv_sequence_number
);
534 // encode Authentication TLV, if needed
535 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
536 && (ei
->params
.auth_keychain
!= NULL
)) {
537 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, ei
);
540 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
545 for (ALL_LIST_ELEMENTS(pe
->entries
, node2
, nnode2
, te
)) {
546 if (eigrp_nbr_split_horizon_check(te
, ei
))
549 if ((length
+ EIGRP_TLV_MAX_IPV4_BYTE
) > eigrp_mtu
) {
550 eigrp_update_place_on_nbr_queue(nbr
, ep
, seq_no
,
554 length
= EIGRP_HEADER_LEN
;
555 ep
= eigrp_packet_new(eigrp_mtu
, nbr
);
556 eigrp_packet_header_init(
557 EIGRP_OPC_UPDATE
, nbr
->ei
->eigrp
, ep
->s
,
558 EIGRP_EOT_FLAG
, seq_no
,
559 nbr
->recv_sequence_number
);
561 if ((ei
->params
.auth_type
562 == EIGRP_AUTH_TYPE_MD5
)
563 && (ei
->params
.auth_keychain
!= NULL
)) {
565 eigrp_add_authTLV_MD5_to_stream(
569 /* Get destination address from prefix */
570 dest_addr
= pe
->destination
;
572 /* Check if any list fits */
573 if (eigrp_update_prefix_apply(
574 eigrp
, ei
, EIGRP_FILTER_OUT
, dest_addr
))
577 length
+= eigrp_add_internalTLV_to_stream(ep
->s
,
583 eigrp_update_place_on_nbr_queue(nbr
, ep
, seq_no
, length
);
584 eigrp
->sequence_number
= seq_no
++;
587 void eigrp_update_send(struct eigrp_interface
*ei
)
589 struct eigrp_packet
*ep
;
590 struct listnode
*node
, *nnode
;
591 struct eigrp_prefix_descriptor
*pe
;
593 struct eigrp
*eigrp
= ei
->eigrp
;
594 struct prefix
*dest_addr
;
595 uint32_t seq_no
= eigrp
->sequence_number
;
596 uint16_t eigrp_mtu
= EIGRP_PACKET_MTU(ei
->ifp
->mtu
);
598 if (ei
->nbrs
->count
== 0)
601 uint16_t length
= EIGRP_HEADER_LEN
;
603 ep
= eigrp_packet_new(eigrp_mtu
, NULL
);
605 /* Prepare EIGRP INIT UPDATE header */
606 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
, 0, seq_no
, 0);
608 // encode Authentication TLV, if needed
609 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
610 && (ei
->params
.auth_keychain
!= NULL
)) {
611 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, ei
);
615 for (ALL_LIST_ELEMENTS(ei
->eigrp
->topology_changes_internalIPV4
, node
,
617 struct eigrp_route_descriptor
*ne
;
619 if (!(pe
->req_action
& EIGRP_FSM_NEED_UPDATE
))
622 ne
= listnode_head(pe
->entries
);
623 if (eigrp_nbr_split_horizon_check(ne
, ei
))
626 if ((length
+ EIGRP_TLV_MAX_IPV4_BYTE
) > eigrp_mtu
) {
627 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
628 && (ei
->params
.auth_keychain
!= NULL
)) {
629 eigrp_make_md5_digest(ei
, ep
->s
,
630 EIGRP_AUTH_UPDATE_FLAG
);
633 eigrp_packet_checksum(ei
, ep
->s
, length
);
636 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
638 ep
->sequence_number
= seq_no
;
640 eigrp_update_send_to_all_nbrs(ei
, ep
);
642 length
= EIGRP_HEADER_LEN
;
643 ep
= eigrp_packet_new(eigrp_mtu
, NULL
);
644 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
,
646 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
647 && (ei
->params
.auth_keychain
!= NULL
)) {
648 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,
653 /* Get destination address from prefix */
654 dest_addr
= pe
->destination
;
656 if (eigrp_update_prefix_apply(eigrp
, ei
, EIGRP_FILTER_OUT
,
658 // pe->reported_metric.delay = EIGRP_MAX_METRIC;
661 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
667 eigrp_packet_free(ep
);
671 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
672 && (ei
->params
.auth_keychain
!= NULL
)) {
673 eigrp_make_md5_digest(ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
677 eigrp_packet_checksum(ei
, ep
->s
, length
);
680 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
682 /*This ack number we await from neighbor*/
683 ep
->sequence_number
= eigrp
->sequence_number
;
685 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
686 zlog_debug("Enqueuing Update length[%u] Seq [%u]", length
,
687 ep
->sequence_number
);
689 eigrp_update_send_to_all_nbrs(ei
, ep
);
690 ei
->eigrp
->sequence_number
= seq_no
++;
693 void eigrp_update_send_all(struct eigrp
*eigrp
,
694 struct eigrp_interface
*exception
)
696 struct eigrp_interface
*iface
;
697 struct listnode
*node
, *node2
, *nnode2
;
698 struct eigrp_prefix_descriptor
*pe
;
700 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
)) {
701 if (iface
!= exception
) {
702 eigrp_update_send(iface
);
706 for (ALL_LIST_ELEMENTS(eigrp
->topology_changes_internalIPV4
, node2
,
708 if (pe
->req_action
& EIGRP_FSM_NEED_UPDATE
) {
709 pe
->req_action
&= ~EIGRP_FSM_NEED_UPDATE
;
710 listnode_delete(eigrp
->topology_changes_internalIPV4
,
717 * @fn eigrp_update_send_GR_part
719 * @param[in] nbr contains neighbor who would receive
726 * Function used for sending Graceful restart Update packet
727 * and if there are multiple chunks, send only one of them.
728 * It is called from thread. Do not call it directly.
730 * Uses nbr_gr_packet_type from neighbor.
732 static void eigrp_update_send_GR_part(struct eigrp_neighbor
*nbr
)
734 struct eigrp_packet
*ep
;
735 uint16_t length
= EIGRP_HEADER_LEN
;
736 struct eigrp_prefix_descriptor
*pe
;
737 struct prefix
*dest_addr
;
738 struct eigrp_interface
*ei
= nbr
->ei
;
739 struct eigrp
*eigrp
= ei
->eigrp
;
740 struct list
*prefixes
;
742 unsigned int send_prefixes
;
743 struct route_node
*rn
;
745 /* get prefixes to send to neighbor */
746 prefixes
= nbr
->nbr_gr_prefixes_send
;
750 /* if there already were last packet chunk, we won't continue */
751 if (nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_LAST
)
754 /* if this is first packet chunk, we need to decide,
755 * if there will be one or more chunks */
756 if (nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_FIRST
) {
757 if (prefixes
->count
<= EIGRP_TLV_MAX_IPv4
) {
758 /* there will be only one chunk */
759 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
761 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
763 /* there will be more chunks */
764 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
;
765 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
768 /* this is not first chunk, and we need to decide,
769 * if there will be more chunks */
770 if (prefixes
->count
<= EIGRP_TLV_MAX_IPv4
) {
771 /* this is last chunk */
772 flags
= EIGRP_EOT_FLAG
;
773 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
775 /* there will be more chunks */
777 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
781 ep
= eigrp_packet_new(EIGRP_PACKET_MTU(ei
->ifp
->mtu
), nbr
);
783 /* Prepare EIGRP Graceful restart UPDATE header */
784 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
, flags
,
785 eigrp
->sequence_number
,
786 nbr
->recv_sequence_number
);
788 // encode Authentication TLV, if needed
789 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
790 && (ei
->params
.auth_keychain
!= NULL
)) {
791 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, ei
);
794 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
802 dest_addr
= pe
->destination
;
804 if (eigrp_update_prefix_apply(eigrp
, ei
, EIGRP_FILTER_OUT
,
806 /* do not send filtered route */
807 zlog_info("Filtered prefix %pI4 won't be sent out.",
808 &dest_addr
->u
.prefix4
);
810 /* sending route which wasn't filtered */
811 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
816 * This makes no sense, Filter out then filter in???
817 * Look into this more - DBS
819 if (eigrp_update_prefix_apply(eigrp
, ei
, EIGRP_FILTER_IN
,
821 /* do not send filtered route */
822 zlog_info("Filtered prefix %pI4 will be removed.",
823 &dest_addr
->u
.prefix4
);
825 /* prepare message for FSM */
826 struct eigrp_fsm_action_message fsm_msg
;
828 struct eigrp_route_descriptor
*entry
=
829 eigrp_route_descriptor_lookup(pe
->entries
, nbr
);
831 fsm_msg
.packet_type
= EIGRP_OPC_UPDATE
;
832 fsm_msg
.eigrp
= eigrp
;
833 fsm_msg
.data_type
= EIGRP_INT
;
834 fsm_msg
.adv_router
= nbr
;
835 fsm_msg
.metrics
= pe
->reported_metric
;
836 /* Set delay to MAX */
837 fsm_msg
.metrics
.delay
= EIGRP_MAX_METRIC
;
838 fsm_msg
.entry
= entry
;
841 /* send message to FSM */
842 eigrp_fsm_event(&fsm_msg
);
845 /* NULL the pointer */
848 /* delete processed prefix from list */
849 listnode_delete(prefixes
, pe
);
851 /* if there are enough prefixes, send packet */
852 if (send_prefixes
>= EIGRP_TLV_MAX_IPv4
)
856 /* compute Auth digest */
857 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
858 && (ei
->params
.auth_keychain
!= NULL
)) {
859 eigrp_make_md5_digest(ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
863 eigrp_packet_checksum(ei
, ep
->s
, length
);
866 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
868 /*This ack number we await from neighbor*/
869 ep
->sequence_number
= eigrp
->sequence_number
;
871 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
873 "Enqueuing Update Init Len [%u] Seq [%u] Dest [%pI4]",
874 ep
->length
, ep
->sequence_number
, &ep
->dst
);
876 /*Put packet to retransmission queue*/
877 eigrp_fifo_push(nbr
->retrans_queue
, ep
);
879 if (nbr
->retrans_queue
->count
== 1) {
880 eigrp_send_packet_reliably(nbr
);
885 * @fn eigrp_update_send_GR_thread
887 * @param[in] thread contains neighbor who would receive
890 * @return int always 0
893 * Function used for sending Graceful restart Update packet
894 * in thread, it is prepared for multiple chunks of packet.
896 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
898 void eigrp_update_send_GR_thread(struct thread
*thread
)
900 struct eigrp_neighbor
*nbr
;
902 /* get argument from thread */
903 nbr
= THREAD_ARG(thread
);
904 /* remove this thread pointer */
906 /* if there is packet waiting in queue,
907 * schedule this thread again with small delay */
908 if (nbr
->retrans_queue
->count
> 0) {
909 thread_add_timer_msec(master
, eigrp_update_send_GR_thread
, nbr
,
910 10, &nbr
->t_nbr_send_gr
);
914 /* send GR EIGRP packet chunk */
915 eigrp_update_send_GR_part(nbr
);
917 /* if it wasn't last chunk, schedule this thread again */
918 if (nbr
->nbr_gr_packet_type
!= EIGRP_PACKET_PART_LAST
) {
919 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
924 * @fn eigrp_update_send_GR
926 * @param[in] nbr Neighbor who would receive
929 * @param[in] gr_type Who executed Graceful restart
930 * @param[in] vty Virtual terminal for log output
935 * Function used for sending Graceful restart Update packet:
936 * Creates Update packet with INIT, RS, EOT flags and include
937 * all route except those filtered
939 void eigrp_update_send_GR(struct eigrp_neighbor
*nbr
, enum GR_type gr_type
,
942 struct eigrp_prefix_descriptor
*pe2
;
943 struct list
*prefixes
;
944 struct route_node
*rn
;
945 struct eigrp_interface
*ei
= nbr
->ei
;
946 struct eigrp
*eigrp
= ei
->eigrp
;
948 if (gr_type
== EIGRP_GR_FILTER
) {
949 /* function was called after applying filtration */
951 "Neighbor %pI4 (%s) is resync: route configuration changed",
953 ifindex2ifname(ei
->ifp
->ifindex
, eigrp
->vrf_id
));
954 } else if (gr_type
== EIGRP_GR_MANUAL
) {
955 /* Graceful restart was called manually */
956 zlog_info("Neighbor %pI4 (%s) is resync: manually cleared",
958 ifindex2ifname(ei
->ifp
->ifindex
, eigrp
->vrf_id
));
961 vty_time_print(vty
, 0);
963 "Neighbor %pI4 (%s) is resync: manually cleared\n",
965 ifindex2ifname(ei
->ifp
->ifindex
,
970 prefixes
= list_new();
971 /* add all prefixes from topology table to list */
972 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
977 listnode_add(prefixes
, pe2
);
980 /* save prefixes to neighbor */
981 nbr
->nbr_gr_prefixes_send
= prefixes
;
982 /* indicate, that this is first GR Update packet chunk */
983 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_FIRST
;
984 /* execute packet sending in thread */
985 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
989 * @fn eigrp_update_send_interface_GR
991 * @param[in] ei Interface to neighbors of which
995 * @param[in] gr_type Who executed Graceful restart
996 * @param[in] vty Virtual terminal for log output
1001 * Function used for sending Graceful restart Update packet
1002 * to all neighbors on specified interface.
1004 void eigrp_update_send_interface_GR(struct eigrp_interface
*ei
,
1005 enum GR_type gr_type
, struct vty
*vty
)
1007 struct listnode
*node
;
1008 struct eigrp_neighbor
*nbr
;
1010 /* iterate over all neighbors on eigrp interface */
1011 for (ALL_LIST_ELEMENTS_RO(ei
->nbrs
, node
, nbr
)) {
1012 /* send GR to neighbor */
1013 eigrp_update_send_GR(nbr
, gr_type
, vty
);
1018 * @fn eigrp_update_send_process_GR
1020 * @param[in] eigrp EIGRP process
1021 * @param[in] gr_type Who executed Graceful restart
1022 * @param[in] vty Virtual terminal for log output
1027 * Function used for sending Graceful restart Update packet
1028 * to all neighbors in eigrp process.
1030 void eigrp_update_send_process_GR(struct eigrp
*eigrp
, enum GR_type gr_type
,
1033 struct listnode
*node
;
1034 struct eigrp_interface
*ei
;
1036 /* iterate over all eigrp interfaces */
1037 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, ei
)) {
1038 /* send GR to all neighbors on interface */
1039 eigrp_update_send_interface_GR(ei
, gr_type
, vty
);