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"
66 bool eigrp_update_prefix_apply(struct eigrp
*eigrp
, struct eigrp_interface
*ei
,
67 int in
, struct prefix
*prefix
)
69 struct access_list
*alist
;
70 struct prefix_list
*plist
;
72 alist
= eigrp
->list
[in
];
73 if (alist
&& access_list_apply(alist
, prefix
) == FILTER_DENY
)
76 plist
= eigrp
->prefix
[in
];
77 if (plist
&& prefix_list_apply(plist
, prefix
) == PREFIX_DENY
)
81 if (alist
&& access_list_apply(alist
, prefix
) == FILTER_DENY
)
84 plist
= ei
->prefix
[in
];
85 if (plist
&& prefix_list_apply(plist
, prefix
) == PREFIX_DENY
)
92 * @fn remove_received_prefix_gr
94 * @param[in] nbr_prefixes List of neighbor prefixes
95 * @param[in] recv_prefix Prefix which needs to be removed from
101 * Function is used for removing received prefix
102 * from list of neighbor prefixes
104 static void remove_received_prefix_gr(struct list
*nbr_prefixes
,
105 struct eigrp_prefix_entry
*recv_prefix
)
107 struct listnode
*node1
, *node11
;
108 struct eigrp_prefix_entry
*prefix
= NULL
;
110 /* iterate over all prefixes in list */
111 for (ALL_LIST_ELEMENTS(nbr_prefixes
, node1
, node11
, prefix
)) {
112 /* remove prefix from list if found */
113 if (prefix
== recv_prefix
) {
114 listnode_delete(nbr_prefixes
, prefix
);
120 * @fn eigrp_update_receive_GR_ask
122 * @param[in] eigrp EIGRP process
123 * @param[in] nbr Neighbor update of who we
125 * @param[in] nbr_prefixes Prefixes which weren't advertised
130 * Function is used for notifying FSM about prefixes which
131 * weren't advertised by neighbor:
132 * We will send message to FSM with prefix delay set to infinity.
134 static void eigrp_update_receive_GR_ask(struct eigrp
*eigrp
,
135 struct eigrp_neighbor
*nbr
,
136 struct list
*nbr_prefixes
)
138 struct listnode
*node1
;
139 struct eigrp_prefix_entry
*prefix
;
140 struct eigrp_fsm_action_message fsm_msg
;
142 /* iterate over all prefixes which weren't advertised by neighbor */
143 for (ALL_LIST_ELEMENTS_RO(nbr_prefixes
, node1
, prefix
)) {
144 char buffer
[PREFIX_STRLEN
];
146 "GR receive: Neighbor not advertised %s",
147 prefix2str(prefix
->destination
, buffer
, PREFIX_STRLEN
));
149 fsm_msg
.metrics
= prefix
->reported_metric
;
150 /* set delay to MAX */
151 fsm_msg
.metrics
.delay
= EIGRP_MAX_METRIC
;
153 struct eigrp_nexthop_entry
*entry
=
154 eigrp_prefix_entry_lookup(prefix
->entries
, nbr
);
156 fsm_msg
.packet_type
= EIGRP_OPC_UPDATE
;
157 fsm_msg
.eigrp
= eigrp
;
158 fsm_msg
.data_type
= EIGRP_INT
;
159 fsm_msg
.adv_router
= nbr
;
160 fsm_msg
.entry
= entry
;
161 fsm_msg
.prefix
= prefix
;
163 /* send message to FSM */
164 eigrp_fsm_event(&fsm_msg
);
169 * EIGRP UPDATE read function
171 void eigrp_update_receive(struct eigrp
*eigrp
, struct ip
*iph
,
172 struct eigrp_header
*eigrph
, struct stream
*s
,
173 struct eigrp_interface
*ei
, int size
)
175 struct eigrp_neighbor
*nbr
;
176 struct TLV_IPv4_Internal_type
*tlv
;
177 struct eigrp_prefix_entry
*pe
;
178 struct eigrp_nexthop_entry
*ne
;
183 struct prefix dest_addr
;
184 uint8_t graceful_restart
;
185 uint8_t graceful_restart_final
;
186 struct list
*nbr_prefixes
= NULL
;
188 /* increment statistics. */
191 /* get neighbor struct */
192 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
194 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
197 flags
= ntohl(eigrph
->flags
);
199 if (flags
& EIGRP_CR_FLAG
) {
204 graceful_restart
= 0;
205 graceful_restart_final
= 0;
206 if ((nbr
->recv_sequence_number
) == (ntohl(eigrph
->sequence
)))
209 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
210 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
212 "Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]",
214 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, eigrp
->vrf_id
),
215 inet_ntoa(nbr
->src
), nbr
->recv_sequence_number
, flags
);
218 if ((flags
== (EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
+ EIGRP_EOT_FLAG
))
220 /* Graceful restart Update received with all routes */
222 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
224 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, eigrp
->vrf_id
));
226 /* get all prefixes from neighbor from topology table */
227 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
228 graceful_restart
= 1;
229 graceful_restart_final
= 1;
230 } else if ((flags
== (EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
)) && (!same
)) {
231 /* Graceful restart Update received, routes also in next packet
234 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
236 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, eigrp
->vrf_id
));
238 /* get all prefixes from neighbor from topology table */
239 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
240 /* save prefixes to neighbor for later use */
241 nbr
->nbr_gr_prefixes
= nbr_prefixes
;
242 graceful_restart
= 1;
243 graceful_restart_final
= 0;
244 } else if ((flags
== (EIGRP_EOT_FLAG
)) && (!same
)) {
245 /* If there was INIT+RS Update packet before,
246 * consider this as GR EOT */
248 if (nbr
->nbr_gr_prefixes
!= NULL
) {
249 /* this is final packet of GR */
250 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
251 nbr
->nbr_gr_prefixes
= NULL
;
253 graceful_restart
= 1;
254 graceful_restart_final
= 1;
257 } else if ((flags
== (0)) && (!same
)) {
258 /* If there was INIT+RS Update packet before,
259 * consider this as GR not final packet */
261 if (nbr
->nbr_gr_prefixes
!= NULL
) {
262 /* this is GR not final route packet */
263 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
265 graceful_restart
= 1;
266 graceful_restart_final
= 0;
269 } else if ((flags
& EIGRP_INIT_FLAG
)
270 && (!same
)) { /* When in pending state, send INIT update only
272 already sent before (only if init_sequence
274 if ((nbr
->state
== EIGRP_NEIGHBOR_PENDING
)
275 && (nbr
->init_sequence_number
== 0))
276 eigrp_update_send_init(nbr
);
278 if (nbr
->state
== EIGRP_NEIGHBOR_UP
) {
279 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
280 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
, nbr
);
281 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
282 zlog_info("Neighbor %s (%s) is down: peer restarted",
284 ifindex2ifname(nbr
->ei
->ifp
->ifindex
,
286 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_PENDING
);
287 zlog_info("Neighbor %s (%s) is pending: new adjacency",
289 ifindex2ifname(nbr
->ei
->ifp
->ifindex
,
291 eigrp_update_send_init(nbr
);
295 /*If there is topology information*/
296 while (s
->endp
> s
->getp
) {
297 type
= stream_getw(s
);
299 case EIGRP_TLV_IPv4_INT
:
300 stream_set_getp(s
, s
->getp
- sizeof(uint16_t));
302 tlv
= eigrp_read_ipv4_tlv(s
);
304 /*searching if destination exists */
305 dest_addr
.family
= AF_INET
;
306 dest_addr
.u
.prefix4
= tlv
->destination
;
307 dest_addr
.prefixlen
= tlv
->prefix_length
;
308 struct eigrp_prefix_entry
*dest
=
309 eigrp_topology_table_lookup_ipv4(
310 eigrp
->topology_table
, &dest_addr
);
312 /*if exists it comes to DUAL*/
314 /* remove received prefix from neighbor prefix
316 if (graceful_restart
)
317 remove_received_prefix_gr(nbr_prefixes
,
320 struct eigrp_fsm_action_message msg
;
321 struct eigrp_nexthop_entry
*entry
=
322 eigrp_prefix_entry_lookup(dest
->entries
,
325 msg
.packet_type
= EIGRP_OPC_UPDATE
;
327 msg
.data_type
= EIGRP_INT
;
328 msg
.adv_router
= nbr
;
329 msg
.metrics
= tlv
->metric
;
332 eigrp_fsm_event(&msg
);
334 /*Here comes topology information save*/
335 pe
= eigrp_prefix_entry_new();
336 pe
->serno
= eigrp
->serno
;
338 (struct prefix
*)prefix_ipv4_new();
339 prefix_copy(pe
->destination
, &dest_addr
);
341 pe
->state
= EIGRP_FSM_STATE_PASSIVE
;
342 pe
->nt
= EIGRP_TOPOLOGY_TYPE_REMOTE
;
344 ne
= eigrp_nexthop_entry_new();
346 ne
->adv_router
= nbr
;
347 ne
->reported_metric
= tlv
->metric
;
348 ne
->reported_distance
= eigrp_calculate_metrics(
353 if (eigrp_update_prefix_apply(eigrp
, ei
,
356 ne
->reported_metric
.delay
=
359 ne
->distance
= eigrp_calculate_total_metrics(
362 pe
->fdistance
= pe
->distance
= pe
->rdistance
=
365 ne
->flags
= EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG
;
367 eigrp_prefix_entry_add(eigrp
->topology_table
,
369 eigrp_nexthop_entry_add(eigrp
, pe
, ne
);
370 pe
->distance
= pe
->fdistance
= pe
->rdistance
=
372 pe
->reported_metric
= ne
->total_metric
;
373 eigrp_topology_update_node_flags(eigrp
, pe
);
375 pe
->req_action
|= EIGRP_FSM_NEED_UPDATE
;
377 eigrp
->topology_changes_internalIPV4
,
380 eigrp_IPv4_InternalTLV_free(tlv
);
383 case EIGRP_TLV_IPv4_EXT
:
384 /* DVS: processing of external routes needs packet and fsm work.
385 * for now, lets just not creash the box
388 length
= stream_getw(s
);
389 // -2 for type, -2 for len
390 for (length
-= 4; length
; length
--) {
391 (void)stream_getc(s
);
396 /* ask about prefixes not present in GR update,
397 * if this is final GR packet */
398 if (graceful_restart_final
) {
399 eigrp_update_receive_GR_ask(eigrp
, nbr
, nbr_prefixes
);
403 * We don't need to send separate Ack for INIT Update. INIT will be
404 * acked in EOT Update.
406 if ((nbr
->state
== EIGRP_NEIGHBOR_UP
) && !(flags
== EIGRP_INIT_FLAG
)) {
407 eigrp_hello_send_ack(nbr
);
410 eigrp_query_send_all(eigrp
);
411 eigrp_update_send_all(eigrp
, ei
);
414 list_delete(&nbr_prefixes
);
417 /*send EIGRP Update packet*/
418 void eigrp_update_send_init(struct eigrp_neighbor
*nbr
)
420 struct eigrp_packet
*ep
;
421 uint16_t length
= EIGRP_HEADER_LEN
;
423 ep
= eigrp_packet_new(EIGRP_PACKET_MTU(nbr
->ei
->ifp
->mtu
), nbr
);
425 /* Prepare EIGRP INIT UPDATE header */
426 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
427 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
428 nbr
->ei
->eigrp
->sequence_number
,
429 nbr
->recv_sequence_number
);
431 eigrp_packet_header_init(
432 EIGRP_OPC_UPDATE
, nbr
->ei
->eigrp
, ep
->s
, EIGRP_INIT_FLAG
,
433 nbr
->ei
->eigrp
->sequence_number
, nbr
->recv_sequence_number
);
435 // encode Authentication TLV, if needed
436 if ((nbr
->ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
437 && (nbr
->ei
->params
.auth_keychain
!= NULL
)) {
438 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, nbr
->ei
);
439 eigrp_make_md5_digest(nbr
->ei
, ep
->s
,
440 EIGRP_AUTH_UPDATE_INIT_FLAG
);
444 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
447 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
449 /*This ack number we await from neighbor*/
450 nbr
->init_sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
451 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
452 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
453 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
454 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
456 /*Put packet to retransmission queue*/
457 eigrp_fifo_push(nbr
->retrans_queue
, ep
);
459 if (nbr
->retrans_queue
->count
== 1) {
460 eigrp_send_packet_reliably(nbr
);
464 static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor
*nbr
,
465 struct eigrp_packet
*ep
,
466 uint32_t seq_no
, int length
)
468 if ((nbr
->ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
469 && (nbr
->ei
->params
.auth_keychain
!= NULL
)) {
470 eigrp_make_md5_digest(nbr
->ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
474 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
477 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
479 /*This ack number we await from neighbor*/
480 ep
->sequence_number
= seq_no
;
482 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
483 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
484 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
486 /*Put packet to retransmission queue*/
487 eigrp_fifo_push(nbr
->retrans_queue
, ep
);
489 if (nbr
->retrans_queue
->count
== 1)
490 eigrp_send_packet_reliably(nbr
);
493 static void eigrp_update_send_to_all_nbrs(struct eigrp_interface
*ei
,
494 struct eigrp_packet
*ep
)
496 struct listnode
*node
, *nnode
;
497 struct eigrp_neighbor
*nbr
;
498 bool packet_sent
= false;
500 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node
, nnode
, nbr
)) {
501 struct eigrp_packet
*ep_dup
;
503 if (nbr
->state
!= EIGRP_NEIGHBOR_UP
)
507 ep_dup
= eigrp_packet_duplicate(ep
, NULL
);
513 /*Put packet to retransmission queue*/
514 eigrp_fifo_push(nbr
->retrans_queue
, ep_dup
);
516 if (nbr
->retrans_queue
->count
== 1) {
517 eigrp_send_packet_reliably(nbr
);
522 eigrp_packet_free(ep
);
525 void eigrp_update_send_EOT(struct eigrp_neighbor
*nbr
)
527 struct eigrp_packet
*ep
;
528 uint16_t length
= EIGRP_HEADER_LEN
;
529 struct eigrp_nexthop_entry
*te
;
530 struct eigrp_prefix_entry
*pe
;
531 struct listnode
*node2
, *nnode2
;
532 struct eigrp_interface
*ei
= nbr
->ei
;
533 struct eigrp
*eigrp
= ei
->eigrp
;
534 struct prefix
*dest_addr
;
535 uint32_t seq_no
= eigrp
->sequence_number
;
536 uint16_t eigrp_mtu
= EIGRP_PACKET_MTU(ei
->ifp
->mtu
);
537 struct route_node
*rn
;
539 ep
= eigrp_packet_new(eigrp_mtu
, nbr
);
541 /* Prepare EIGRP EOT UPDATE header */
542 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
, EIGRP_EOT_FLAG
,
543 seq_no
, nbr
->recv_sequence_number
);
545 // encode Authentication TLV, if needed
546 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
547 && (ei
->params
.auth_keychain
!= NULL
)) {
548 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, ei
);
551 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
556 for (ALL_LIST_ELEMENTS(pe
->entries
, node2
, nnode2
, te
)) {
557 if (eigrp_nbr_split_horizon_check(te
, ei
))
560 if ((length
+ EIGRP_TLV_MAX_IPV4_BYTE
) > eigrp_mtu
) {
561 eigrp_update_place_on_nbr_queue(nbr
, ep
, seq_no
,
565 length
= EIGRP_HEADER_LEN
;
566 ep
= eigrp_packet_new(eigrp_mtu
, nbr
);
567 eigrp_packet_header_init(
568 EIGRP_OPC_UPDATE
, nbr
->ei
->eigrp
, ep
->s
,
569 EIGRP_EOT_FLAG
, seq_no
,
570 nbr
->recv_sequence_number
);
572 if ((ei
->params
.auth_type
573 == EIGRP_AUTH_TYPE_MD5
)
574 && (ei
->params
.auth_keychain
!= NULL
)) {
576 eigrp_add_authTLV_MD5_to_stream(
580 /* Get destination address from prefix */
581 dest_addr
= pe
->destination
;
583 /* Check if any list fits */
584 if (eigrp_update_prefix_apply(
585 eigrp
, ei
, EIGRP_FILTER_OUT
, dest_addr
))
588 length
+= eigrp_add_internalTLV_to_stream(ep
->s
,
594 eigrp_update_place_on_nbr_queue(nbr
, ep
, seq_no
, length
);
595 eigrp
->sequence_number
= seq_no
++;
598 void eigrp_update_send(struct eigrp_interface
*ei
)
600 struct eigrp_packet
*ep
;
601 struct listnode
*node
, *nnode
;
602 struct eigrp_prefix_entry
*pe
;
604 struct eigrp
*eigrp
= ei
->eigrp
;
605 struct prefix
*dest_addr
;
606 uint32_t seq_no
= eigrp
->sequence_number
;
607 uint16_t eigrp_mtu
= EIGRP_PACKET_MTU(ei
->ifp
->mtu
);
609 if (ei
->nbrs
->count
== 0)
612 uint16_t length
= EIGRP_HEADER_LEN
;
614 ep
= eigrp_packet_new(eigrp_mtu
, NULL
);
616 /* Prepare EIGRP INIT UPDATE header */
617 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
, 0, seq_no
, 0);
619 // encode Authentication TLV, if needed
620 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
621 && (ei
->params
.auth_keychain
!= NULL
)) {
622 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, ei
);
626 for (ALL_LIST_ELEMENTS(ei
->eigrp
->topology_changes_internalIPV4
, node
,
628 struct eigrp_nexthop_entry
*ne
;
630 if (!(pe
->req_action
& EIGRP_FSM_NEED_UPDATE
))
633 ne
= listnode_head(pe
->entries
);
634 if (eigrp_nbr_split_horizon_check(ne
, ei
))
637 if ((length
+ EIGRP_TLV_MAX_IPV4_BYTE
) > eigrp_mtu
) {
638 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
639 && (ei
->params
.auth_keychain
!= NULL
)) {
640 eigrp_make_md5_digest(ei
, ep
->s
,
641 EIGRP_AUTH_UPDATE_FLAG
);
644 eigrp_packet_checksum(ei
, ep
->s
, length
);
647 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
649 ep
->sequence_number
= seq_no
;
651 eigrp_update_send_to_all_nbrs(ei
, ep
);
653 length
= EIGRP_HEADER_LEN
;
654 ep
= eigrp_packet_new(eigrp_mtu
, NULL
);
655 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
,
657 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
658 && (ei
->params
.auth_keychain
!= NULL
)) {
659 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,
664 /* Get destination address from prefix */
665 dest_addr
= pe
->destination
;
667 if (eigrp_update_prefix_apply(eigrp
, ei
, EIGRP_FILTER_OUT
,
669 // pe->reported_metric.delay = EIGRP_MAX_METRIC;
672 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
678 eigrp_packet_free(ep
);
682 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
683 && (ei
->params
.auth_keychain
!= NULL
)) {
684 eigrp_make_md5_digest(ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
688 eigrp_packet_checksum(ei
, ep
->s
, length
);
691 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
693 /*This ack number we await from neighbor*/
694 ep
->sequence_number
= eigrp
->sequence_number
;
696 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
697 zlog_debug("Enqueuing Update length[%u] Seq [%u]", length
,
698 ep
->sequence_number
);
700 eigrp_update_send_to_all_nbrs(ei
, ep
);
701 ei
->eigrp
->sequence_number
= seq_no
++;
704 void eigrp_update_send_all(struct eigrp
*eigrp
,
705 struct eigrp_interface
*exception
)
707 struct eigrp_interface
*iface
;
708 struct listnode
*node
, *node2
, *nnode2
;
709 struct eigrp_prefix_entry
*pe
;
711 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
)) {
712 if (iface
!= exception
) {
713 eigrp_update_send(iface
);
717 for (ALL_LIST_ELEMENTS(eigrp
->topology_changes_internalIPV4
, node2
,
719 if (pe
->req_action
& EIGRP_FSM_NEED_UPDATE
) {
720 pe
->req_action
&= ~EIGRP_FSM_NEED_UPDATE
;
721 listnode_delete(eigrp
->topology_changes_internalIPV4
,
728 * @fn eigrp_update_send_GR_part
730 * @param[in] nbr contains neighbor who would receive
737 * Function used for sending Graceful restart Update packet
738 * and if there are multiple chunks, send only one of them.
739 * It is called from thread. Do not call it directly.
741 * Uses nbr_gr_packet_type from neighbor.
743 static void eigrp_update_send_GR_part(struct eigrp_neighbor
*nbr
)
745 struct eigrp_packet
*ep
;
746 uint16_t length
= EIGRP_HEADER_LEN
;
747 struct eigrp_prefix_entry
*pe
;
748 struct prefix
*dest_addr
;
749 struct eigrp_interface
*ei
= nbr
->ei
;
750 struct eigrp
*eigrp
= ei
->eigrp
;
751 struct list
*prefixes
;
753 unsigned int send_prefixes
;
754 struct route_node
*rn
;
756 /* get prefixes to send to neighbor */
757 prefixes
= nbr
->nbr_gr_prefixes_send
;
761 /* if there already were last packet chunk, we won't continue */
762 if (nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_LAST
)
765 /* if this is first packet chunk, we need to decide,
766 * if there will be one or more chunks */
767 if (nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_FIRST
) {
768 if (prefixes
->count
<= EIGRP_TLV_MAX_IPv4
) {
769 /* there will be only one chunk */
770 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
772 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
774 /* there will be more chunks */
775 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
;
776 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
779 /* this is not first chunk, and we need to decide,
780 * if there will be more chunks */
781 if (prefixes
->count
<= EIGRP_TLV_MAX_IPv4
) {
782 /* this is last chunk */
783 flags
= EIGRP_EOT_FLAG
;
784 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
786 /* there will be more chunks */
788 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
792 ep
= eigrp_packet_new(EIGRP_PACKET_MTU(ei
->ifp
->mtu
), nbr
);
794 /* Prepare EIGRP Graceful restart UPDATE header */
795 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
, flags
,
796 eigrp
->sequence_number
,
797 nbr
->recv_sequence_number
);
799 // encode Authentication TLV, if needed
800 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
801 && (ei
->params
.auth_keychain
!= NULL
)) {
802 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, ei
);
805 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
813 dest_addr
= pe
->destination
;
815 if (eigrp_update_prefix_apply(eigrp
, ei
, EIGRP_FILTER_OUT
,
817 /* do not send filtered route */
818 zlog_info("Filtered prefix %s won't be sent out.",
819 inet_ntoa(dest_addr
->u
.prefix4
));
821 /* sending route which wasn't filtered */
822 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
827 * This makes no sense, Filter out then filter in???
828 * Look into this more - DBS
830 if (eigrp_update_prefix_apply(eigrp
, ei
, EIGRP_FILTER_IN
,
832 /* do not send filtered route */
833 zlog_info("Filtered prefix %s will be removed.",
834 inet_ntoa(dest_addr
->u
.prefix4
));
836 /* prepare message for FSM */
837 struct eigrp_fsm_action_message fsm_msg
;
839 struct eigrp_nexthop_entry
*entry
=
840 eigrp_prefix_entry_lookup(pe
->entries
, nbr
);
842 fsm_msg
.packet_type
= EIGRP_OPC_UPDATE
;
843 fsm_msg
.eigrp
= eigrp
;
844 fsm_msg
.data_type
= EIGRP_INT
;
845 fsm_msg
.adv_router
= nbr
;
846 fsm_msg
.metrics
= pe
->reported_metric
;
847 /* Set delay to MAX */
848 fsm_msg
.metrics
.delay
= EIGRP_MAX_METRIC
;
849 fsm_msg
.entry
= entry
;
852 /* send message to FSM */
853 eigrp_fsm_event(&fsm_msg
);
856 /* NULL the pointer */
859 /* delete processed prefix from list */
860 listnode_delete(prefixes
, pe
);
862 /* if there are enough prefixes, send packet */
863 if (send_prefixes
>= EIGRP_TLV_MAX_IPv4
)
867 /* compute Auth digest */
868 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
869 && (ei
->params
.auth_keychain
!= NULL
)) {
870 eigrp_make_md5_digest(ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
874 eigrp_packet_checksum(ei
, ep
->s
, length
);
877 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
879 /*This ack number we await from neighbor*/
880 ep
->sequence_number
= eigrp
->sequence_number
;
882 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
883 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
884 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
886 /*Put packet to retransmission queue*/
887 eigrp_fifo_push(nbr
->retrans_queue
, ep
);
889 if (nbr
->retrans_queue
->count
== 1) {
890 eigrp_send_packet_reliably(nbr
);
895 * @fn eigrp_update_send_GR_thread
897 * @param[in] thread contains neighbor who would receive
900 * @return int always 0
903 * Function used for sending Graceful restart Update packet
904 * in thread, it is prepared for multiple chunks of packet.
906 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
908 int eigrp_update_send_GR_thread(struct thread
*thread
)
910 struct eigrp_neighbor
*nbr
;
912 /* get argument from thread */
913 nbr
= THREAD_ARG(thread
);
914 /* remove this thread pointer */
915 nbr
->t_nbr_send_gr
= NULL
;
917 /* if there is packet waiting in queue,
918 * schedule this thread again with small delay */
919 if (nbr
->retrans_queue
->count
> 0) {
920 nbr
->t_nbr_send_gr
= NULL
;
921 thread_add_timer_msec(master
, eigrp_update_send_GR_thread
, nbr
,
922 10, &nbr
->t_nbr_send_gr
);
926 /* send GR EIGRP packet chunk */
927 eigrp_update_send_GR_part(nbr
);
929 /* if it wasn't last chunk, schedule this thread again */
930 if (nbr
->nbr_gr_packet_type
!= EIGRP_PACKET_PART_LAST
) {
931 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
932 nbr
->t_nbr_send_gr
= NULL
;
939 * @fn eigrp_update_send_GR
941 * @param[in] nbr Neighbor who would receive
944 * @param[in] gr_type Who executed Graceful restart
945 * @param[in] vty Virtual terminal for log output
950 * Function used for sending Graceful restart Update packet:
951 * Creates Update packet with INIT, RS, EOT flags and include
952 * all route except those filtered
954 void eigrp_update_send_GR(struct eigrp_neighbor
*nbr
, enum GR_type gr_type
,
957 struct eigrp_prefix_entry
*pe2
;
958 struct list
*prefixes
;
959 struct route_node
*rn
;
960 struct eigrp_interface
*ei
= nbr
->ei
;
961 struct eigrp
*eigrp
= ei
->eigrp
;
963 if (gr_type
== EIGRP_GR_FILTER
) {
964 /* function was called after applying filtration */
966 "Neighbor %s (%s) is resync: route configuration changed",
968 ifindex2ifname(ei
->ifp
->ifindex
, eigrp
->vrf_id
));
969 } else if (gr_type
== EIGRP_GR_MANUAL
) {
970 /* Graceful restart was called manually */
971 zlog_info("Neighbor %s (%s) is resync: manually cleared",
973 ifindex2ifname(ei
->ifp
->ifindex
, eigrp
->vrf_id
));
976 vty_time_print(vty
, 0);
978 "Neighbor %s (%s) is resync: manually cleared\n",
980 ifindex2ifname(ei
->ifp
->ifindex
,
985 prefixes
= list_new();
986 /* add all prefixes from topology table to list */
987 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
992 listnode_add(prefixes
, pe2
);
995 /* save prefixes to neighbor */
996 nbr
->nbr_gr_prefixes_send
= prefixes
;
997 /* indicate, that this is first GR Update packet chunk */
998 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_FIRST
;
999 /* execute packet sending in thread */
1000 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
1001 nbr
->t_nbr_send_gr
= NULL
;
1005 * @fn eigrp_update_send_interface_GR
1007 * @param[in] ei Interface to neighbors of which
1011 * @param[in] gr_type Who executed Graceful restart
1012 * @param[in] vty Virtual terminal for log output
1017 * Function used for sending Graceful restart Update packet
1018 * to all neighbors on specified interface.
1020 void eigrp_update_send_interface_GR(struct eigrp_interface
*ei
,
1021 enum GR_type gr_type
, struct vty
*vty
)
1023 struct listnode
*node
;
1024 struct eigrp_neighbor
*nbr
;
1026 /* iterate over all neighbors on eigrp interface */
1027 for (ALL_LIST_ELEMENTS_RO(ei
->nbrs
, node
, nbr
)) {
1028 /* send GR to neighbor */
1029 eigrp_update_send_GR(nbr
, gr_type
, vty
);
1034 * @fn eigrp_update_send_process_GR
1036 * @param[in] eigrp EIGRP process
1037 * @param[in] gr_type Who executed Graceful restart
1038 * @param[in] vty Virtual terminal for log output
1043 * Function used for sending Graceful restart Update packet
1044 * to all neighbors in eigrp process.
1046 void eigrp_update_send_process_GR(struct eigrp
*eigrp
, enum GR_type gr_type
,
1049 struct listnode
*node
;
1050 struct eigrp_interface
*ei
;
1052 /* iterate over all eigrp interfaces */
1053 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, ei
)) {
1054 /* send GR to all neighbors on interface */
1055 eigrp_update_send_interface_GR(ei
, gr_type
, vty
);