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_types.h"
53 #include "eigrpd/eigrp_structs.h"
54 #include "eigrpd/eigrpd.h"
55 #include "eigrpd/eigrp_interface.h"
56 #include "eigrpd/eigrp_neighbor.h"
57 #include "eigrpd/eigrp_packet.h"
58 #include "eigrpd/eigrp_zebra.h"
59 #include "eigrpd/eigrp_vty.h"
60 #include "eigrpd/eigrp_dump.h"
61 #include "eigrpd/eigrp_macros.h"
62 #include "eigrpd/eigrp_topology.h"
63 #include "eigrpd/eigrp_fsm.h"
64 #include "eigrpd/eigrp_network.h"
65 #include "eigrpd/eigrp_memory.h"
66 #include "eigrpd/eigrp_metric.h"
68 bool eigrp_update_prefix_apply(struct eigrp
*eigrp
, struct eigrp_interface
*ei
,
69 int in
, struct prefix
*prefix
)
71 struct access_list
*alist
;
72 struct prefix_list
*plist
;
74 alist
= eigrp
->list
[in
];
75 if (alist
&& access_list_apply(alist
, prefix
) == FILTER_DENY
)
78 plist
= eigrp
->prefix
[in
];
79 if (plist
&& prefix_list_apply(plist
, prefix
) == PREFIX_DENY
)
83 if (alist
&& access_list_apply(alist
, prefix
) == FILTER_DENY
)
86 plist
= ei
->prefix
[in
];
87 if (plist
&& prefix_list_apply(plist
, prefix
) == PREFIX_DENY
)
94 * @fn remove_received_prefix_gr
96 * @param[in] nbr_prefixes List of neighbor prefixes
97 * @param[in] recv_prefix Prefix which needs to be removed from
103 * Function is used for removing received prefix
104 * from list of neighbor prefixes
107 remove_received_prefix_gr(struct list
*nbr_prefixes
,
108 struct eigrp_prefix_descriptor
*recv_prefix
)
110 struct listnode
*node1
, *node11
;
111 struct eigrp_prefix_descriptor
*prefix
= NULL
;
113 /* iterate over all prefixes in list */
114 for (ALL_LIST_ELEMENTS(nbr_prefixes
, node1
, node11
, prefix
)) {
115 /* remove prefix from list if found */
116 if (prefix
== recv_prefix
) {
117 listnode_delete(nbr_prefixes
, prefix
);
123 * @fn eigrp_update_receive_GR_ask
125 * @param[in] eigrp EIGRP process
126 * @param[in] nbr Neighbor update of who we
128 * @param[in] nbr_prefixes Prefixes which weren't advertised
133 * Function is used for notifying FSM about prefixes which
134 * weren't advertised by neighbor:
135 * We will send message to FSM with prefix delay set to infinity.
137 static void eigrp_update_receive_GR_ask(struct eigrp
*eigrp
,
138 struct eigrp_neighbor
*nbr
,
139 struct list
*nbr_prefixes
)
141 struct listnode
*node1
;
142 struct eigrp_prefix_descriptor
*prefix
;
143 struct eigrp_fsm_action_message fsm_msg
;
145 /* iterate over all prefixes which weren't advertised by neighbor */
146 for (ALL_LIST_ELEMENTS_RO(nbr_prefixes
, node1
, prefix
)) {
147 zlog_debug("GR receive: Neighbor not advertised %pFX",
148 prefix
->destination
);
150 fsm_msg
.metrics
= prefix
->reported_metric
;
151 /* set delay to MAX */
152 fsm_msg
.metrics
.delay
= EIGRP_MAX_METRIC
;
154 struct eigrp_route_descriptor
*entry
=
155 eigrp_route_descriptor_lookup(prefix
->entries
, nbr
);
157 fsm_msg
.packet_type
= EIGRP_OPC_UPDATE
;
158 fsm_msg
.eigrp
= eigrp
;
159 fsm_msg
.data_type
= EIGRP_INT
;
160 fsm_msg
.adv_router
= nbr
;
161 fsm_msg
.entry
= entry
;
162 fsm_msg
.prefix
= prefix
;
164 /* send message to FSM */
165 eigrp_fsm_event(&fsm_msg
);
170 * EIGRP UPDATE read function
172 void eigrp_update_receive(struct eigrp
*eigrp
, struct ip
*iph
,
173 struct eigrp_header
*eigrph
, struct stream
*s
,
174 struct eigrp_interface
*ei
, int size
)
176 struct eigrp_neighbor
*nbr
;
177 struct TLV_IPv4_Internal_type
*tlv
;
178 struct eigrp_prefix_descriptor
*pe
;
179 struct eigrp_route_descriptor
*ne
;
184 struct prefix dest_addr
;
185 uint8_t graceful_restart
;
186 uint8_t graceful_restart_final
;
187 struct list
*nbr_prefixes
= NULL
;
189 /* increment statistics. */
192 /* get neighbor struct */
193 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
195 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
198 flags
= ntohl(eigrph
->flags
);
200 if (flags
& EIGRP_CR_FLAG
) {
205 graceful_restart
= 0;
206 graceful_restart_final
= 0;
207 if ((nbr
->recv_sequence_number
) == (ntohl(eigrph
->sequence
)))
210 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
211 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
213 "Processing Update size[%u] int(%s) nbr(%pI4) seq [%u] flags [%0x]",
215 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, eigrp
->vrf_id
),
216 &nbr
->src
, nbr
->recv_sequence_number
, flags
);
219 if ((flags
== (EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
+ EIGRP_EOT_FLAG
))
221 /* Graceful restart Update received with all routes */
223 zlog_info("Neighbor %pI4 (%s) is resync: peer graceful-restart",
225 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, eigrp
->vrf_id
));
227 /* get all prefixes from neighbor from topology table */
228 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
229 graceful_restart
= 1;
230 graceful_restart_final
= 1;
231 } else if ((flags
== (EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
)) && (!same
)) {
232 /* Graceful restart Update received, routes also in next packet
235 zlog_info("Neighbor %pI4 (%s) is resync: peer graceful-restart",
237 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, eigrp
->vrf_id
));
239 /* get all prefixes from neighbor from topology table */
240 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
241 /* save prefixes to neighbor for later use */
242 nbr
->nbr_gr_prefixes
= nbr_prefixes
;
243 graceful_restart
= 1;
244 graceful_restart_final
= 0;
245 } else if ((flags
== (EIGRP_EOT_FLAG
)) && (!same
)) {
246 /* If there was INIT+RS Update packet before,
247 * consider this as GR EOT */
249 if (nbr
->nbr_gr_prefixes
!= NULL
) {
250 /* this is final packet of GR */
251 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
252 nbr
->nbr_gr_prefixes
= NULL
;
254 graceful_restart
= 1;
255 graceful_restart_final
= 1;
258 } else if ((flags
== (0)) && (!same
)) {
259 /* If there was INIT+RS Update packet before,
260 * consider this as GR not final packet */
262 if (nbr
->nbr_gr_prefixes
!= NULL
) {
263 /* this is GR not final route packet */
264 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
266 graceful_restart
= 1;
267 graceful_restart_final
= 0;
270 } else if ((flags
& EIGRP_INIT_FLAG
)
271 && (!same
)) { /* When in pending state, send INIT update only
273 already sent before (only if init_sequence
275 if ((nbr
->state
== EIGRP_NEIGHBOR_PENDING
)
276 && (nbr
->init_sequence_number
== 0))
277 eigrp_update_send_init(nbr
);
279 if (nbr
->state
== EIGRP_NEIGHBOR_UP
) {
280 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
281 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
, nbr
);
282 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
283 zlog_info("Neighbor %pI4 (%s) is down: peer restarted",
285 ifindex2ifname(nbr
->ei
->ifp
->ifindex
,
287 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_PENDING
);
289 "Neighbor %pI4 (%s) is pending: new adjacency",
291 ifindex2ifname(nbr
->ei
->ifp
->ifindex
,
293 eigrp_update_send_init(nbr
);
297 /*If there is topology information*/
298 while (s
->endp
> s
->getp
) {
299 type
= stream_getw(s
);
301 case EIGRP_TLV_IPv4_INT
:
302 stream_set_getp(s
, s
->getp
- sizeof(uint16_t));
304 tlv
= eigrp_read_ipv4_tlv(s
);
306 /*searching if destination exists */
307 dest_addr
.family
= AF_INET
;
308 dest_addr
.u
.prefix4
= tlv
->destination
;
309 dest_addr
.prefixlen
= tlv
->prefix_length
;
310 struct eigrp_prefix_descriptor
*dest
=
311 eigrp_topology_table_lookup_ipv4(
312 eigrp
->topology_table
, &dest_addr
);
314 /*if exists it comes to DUAL*/
316 /* remove received prefix from neighbor prefix
318 if (graceful_restart
)
319 remove_received_prefix_gr(nbr_prefixes
,
322 struct eigrp_fsm_action_message msg
;
323 struct eigrp_route_descriptor
*entry
=
324 eigrp_route_descriptor_lookup(
327 msg
.packet_type
= EIGRP_OPC_UPDATE
;
329 msg
.data_type
= EIGRP_INT
;
330 msg
.adv_router
= nbr
;
331 msg
.metrics
= tlv
->metric
;
334 eigrp_fsm_event(&msg
);
336 /*Here comes topology information save*/
337 pe
= eigrp_prefix_descriptor_new();
338 pe
->serno
= eigrp
->serno
;
340 (struct prefix
*)prefix_ipv4_new();
341 prefix_copy(pe
->destination
, &dest_addr
);
343 pe
->state
= EIGRP_FSM_STATE_PASSIVE
;
344 pe
->nt
= EIGRP_TOPOLOGY_TYPE_REMOTE
;
346 ne
= eigrp_route_descriptor_new();
348 ne
->adv_router
= nbr
;
349 ne
->reported_metric
= tlv
->metric
;
350 ne
->reported_distance
= eigrp_calculate_metrics(
355 if (eigrp_update_prefix_apply(eigrp
, ei
,
358 ne
->reported_metric
.delay
=
361 ne
->distance
= eigrp_calculate_total_metrics(
364 pe
->fdistance
= pe
->distance
= pe
->rdistance
=
368 EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG
;
370 eigrp_prefix_descriptor_add(
371 eigrp
->topology_table
, pe
);
372 eigrp_route_descriptor_add(eigrp
, pe
, ne
);
373 pe
->distance
= pe
->fdistance
= pe
->rdistance
=
375 pe
->reported_metric
= ne
->total_metric
;
376 eigrp_topology_update_node_flags(eigrp
, pe
);
378 pe
->req_action
|= EIGRP_FSM_NEED_UPDATE
;
380 eigrp
->topology_changes_internalIPV4
,
383 eigrp_IPv4_InternalTLV_free(tlv
);
386 case EIGRP_TLV_IPv4_EXT
:
387 /* DVS: processing of external routes needs packet and fsm work.
388 * for now, lets just not creash the box
391 length
= stream_getw(s
);
392 // -2 for type, -2 for len
393 for (length
-= 4; length
; length
--) {
394 (void)stream_getc(s
);
399 /* ask about prefixes not present in GR update,
400 * if this is final GR packet */
401 if (graceful_restart_final
) {
402 eigrp_update_receive_GR_ask(eigrp
, nbr
, nbr_prefixes
);
406 * We don't need to send separate Ack for INIT Update. INIT will be
407 * acked in EOT Update.
409 if ((nbr
->state
== EIGRP_NEIGHBOR_UP
) && !(flags
== EIGRP_INIT_FLAG
)) {
410 eigrp_hello_send_ack(nbr
);
413 eigrp_query_send_all(eigrp
);
414 eigrp_update_send_all(eigrp
, ei
);
417 list_delete(&nbr_prefixes
);
420 /*send EIGRP Update packet*/
421 void eigrp_update_send_init(struct eigrp_neighbor
*nbr
)
423 struct eigrp_packet
*ep
;
424 uint16_t length
= EIGRP_HEADER_LEN
;
426 ep
= eigrp_packet_new(EIGRP_PACKET_MTU(nbr
->ei
->ifp
->mtu
), nbr
);
428 /* Prepare EIGRP INIT UPDATE header */
429 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
430 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
431 nbr
->ei
->eigrp
->sequence_number
,
432 nbr
->recv_sequence_number
);
434 eigrp_packet_header_init(
435 EIGRP_OPC_UPDATE
, nbr
->ei
->eigrp
, ep
->s
, EIGRP_INIT_FLAG
,
436 nbr
->ei
->eigrp
->sequence_number
, nbr
->recv_sequence_number
);
438 // encode Authentication TLV, if needed
439 if ((nbr
->ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
440 && (nbr
->ei
->params
.auth_keychain
!= NULL
)) {
441 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, nbr
->ei
);
442 eigrp_make_md5_digest(nbr
->ei
, ep
->s
,
443 EIGRP_AUTH_UPDATE_INIT_FLAG
);
447 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
450 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
452 /*This ack number we await from neighbor*/
453 nbr
->init_sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
454 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
455 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
457 "Enqueuing Update Init Len [%u] Seq [%u] Dest [%pI4]",
458 ep
->length
, ep
->sequence_number
, &ep
->dst
);
460 /*Put packet to retransmission queue*/
461 eigrp_fifo_push(nbr
->retrans_queue
, ep
);
463 if (nbr
->retrans_queue
->count
== 1) {
464 eigrp_send_packet_reliably(nbr
);
468 static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor
*nbr
,
469 struct eigrp_packet
*ep
,
470 uint32_t seq_no
, int length
)
472 if ((nbr
->ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
473 && (nbr
->ei
->params
.auth_keychain
!= NULL
)) {
474 eigrp_make_md5_digest(nbr
->ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
478 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
481 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
483 /*This ack number we await from neighbor*/
484 ep
->sequence_number
= seq_no
;
486 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
488 "Enqueuing Update Init Len [%u] Seq [%u] Dest [%pI4]",
489 ep
->length
, ep
->sequence_number
, &ep
->dst
);
491 /*Put packet to retransmission queue*/
492 eigrp_fifo_push(nbr
->retrans_queue
, ep
);
494 if (nbr
->retrans_queue
->count
== 1)
495 eigrp_send_packet_reliably(nbr
);
498 static void eigrp_update_send_to_all_nbrs(struct eigrp_interface
*ei
,
499 struct eigrp_packet
*ep
)
501 struct listnode
*node
, *nnode
;
502 struct eigrp_neighbor
*nbr
;
503 bool packet_sent
= false;
505 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node
, nnode
, nbr
)) {
506 struct eigrp_packet
*ep_dup
;
508 if (nbr
->state
!= EIGRP_NEIGHBOR_UP
)
512 ep_dup
= eigrp_packet_duplicate(ep
, NULL
);
518 /*Put packet to retransmission queue*/
519 eigrp_fifo_push(nbr
->retrans_queue
, ep_dup
);
521 if (nbr
->retrans_queue
->count
== 1) {
522 eigrp_send_packet_reliably(nbr
);
527 eigrp_packet_free(ep
);
530 void eigrp_update_send_EOT(struct eigrp_neighbor
*nbr
)
532 struct eigrp_packet
*ep
;
533 uint16_t length
= EIGRP_HEADER_LEN
;
534 struct eigrp_route_descriptor
*te
;
535 struct eigrp_prefix_descriptor
*pe
;
536 struct listnode
*node2
, *nnode2
;
537 struct eigrp_interface
*ei
= nbr
->ei
;
538 struct eigrp
*eigrp
= ei
->eigrp
;
539 struct prefix
*dest_addr
;
540 uint32_t seq_no
= eigrp
->sequence_number
;
541 uint16_t eigrp_mtu
= EIGRP_PACKET_MTU(ei
->ifp
->mtu
);
542 struct route_node
*rn
;
544 ep
= eigrp_packet_new(eigrp_mtu
, nbr
);
546 /* Prepare EIGRP EOT UPDATE header */
547 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
, EIGRP_EOT_FLAG
,
548 seq_no
, nbr
->recv_sequence_number
);
550 // encode Authentication TLV, if needed
551 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
552 && (ei
->params
.auth_keychain
!= NULL
)) {
553 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, ei
);
556 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
561 for (ALL_LIST_ELEMENTS(pe
->entries
, node2
, nnode2
, te
)) {
562 if (eigrp_nbr_split_horizon_check(te
, ei
))
565 if ((length
+ EIGRP_TLV_MAX_IPV4_BYTE
) > eigrp_mtu
) {
566 eigrp_update_place_on_nbr_queue(nbr
, ep
, seq_no
,
570 length
= EIGRP_HEADER_LEN
;
571 ep
= eigrp_packet_new(eigrp_mtu
, nbr
);
572 eigrp_packet_header_init(
573 EIGRP_OPC_UPDATE
, nbr
->ei
->eigrp
, ep
->s
,
574 EIGRP_EOT_FLAG
, seq_no
,
575 nbr
->recv_sequence_number
);
577 if ((ei
->params
.auth_type
578 == EIGRP_AUTH_TYPE_MD5
)
579 && (ei
->params
.auth_keychain
!= NULL
)) {
581 eigrp_add_authTLV_MD5_to_stream(
585 /* Get destination address from prefix */
586 dest_addr
= pe
->destination
;
588 /* Check if any list fits */
589 if (eigrp_update_prefix_apply(
590 eigrp
, ei
, EIGRP_FILTER_OUT
, dest_addr
))
593 length
+= eigrp_add_internalTLV_to_stream(ep
->s
,
599 eigrp_update_place_on_nbr_queue(nbr
, ep
, seq_no
, length
);
600 eigrp
->sequence_number
= seq_no
++;
603 void eigrp_update_send(struct eigrp_interface
*ei
)
605 struct eigrp_packet
*ep
;
606 struct listnode
*node
, *nnode
;
607 struct eigrp_prefix_descriptor
*pe
;
609 struct eigrp
*eigrp
= ei
->eigrp
;
610 struct prefix
*dest_addr
;
611 uint32_t seq_no
= eigrp
->sequence_number
;
612 uint16_t eigrp_mtu
= EIGRP_PACKET_MTU(ei
->ifp
->mtu
);
614 if (ei
->nbrs
->count
== 0)
617 uint16_t length
= EIGRP_HEADER_LEN
;
619 ep
= eigrp_packet_new(eigrp_mtu
, NULL
);
621 /* Prepare EIGRP INIT UPDATE header */
622 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
, 0, seq_no
, 0);
624 // encode Authentication TLV, if needed
625 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
626 && (ei
->params
.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
,
633 struct eigrp_route_descriptor
*ne
;
635 if (!(pe
->req_action
& EIGRP_FSM_NEED_UPDATE
))
638 ne
= listnode_head(pe
->entries
);
639 if (eigrp_nbr_split_horizon_check(ne
, ei
))
642 if ((length
+ EIGRP_TLV_MAX_IPV4_BYTE
) > eigrp_mtu
) {
643 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
644 && (ei
->params
.auth_keychain
!= NULL
)) {
645 eigrp_make_md5_digest(ei
, ep
->s
,
646 EIGRP_AUTH_UPDATE_FLAG
);
649 eigrp_packet_checksum(ei
, ep
->s
, length
);
652 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
654 ep
->sequence_number
= seq_no
;
656 eigrp_update_send_to_all_nbrs(ei
, ep
);
658 length
= EIGRP_HEADER_LEN
;
659 ep
= eigrp_packet_new(eigrp_mtu
, NULL
);
660 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
,
662 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
663 && (ei
->params
.auth_keychain
!= NULL
)) {
664 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,
669 /* Get destination address from prefix */
670 dest_addr
= pe
->destination
;
672 if (eigrp_update_prefix_apply(eigrp
, ei
, EIGRP_FILTER_OUT
,
674 // pe->reported_metric.delay = EIGRP_MAX_METRIC;
677 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
683 eigrp_packet_free(ep
);
687 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
688 && (ei
->params
.auth_keychain
!= NULL
)) {
689 eigrp_make_md5_digest(ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
693 eigrp_packet_checksum(ei
, ep
->s
, length
);
696 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
698 /*This ack number we await from neighbor*/
699 ep
->sequence_number
= eigrp
->sequence_number
;
701 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
702 zlog_debug("Enqueuing Update length[%u] Seq [%u]", length
,
703 ep
->sequence_number
);
705 eigrp_update_send_to_all_nbrs(ei
, ep
);
706 ei
->eigrp
->sequence_number
= seq_no
++;
709 void eigrp_update_send_all(struct eigrp
*eigrp
,
710 struct eigrp_interface
*exception
)
712 struct eigrp_interface
*iface
;
713 struct listnode
*node
, *node2
, *nnode2
;
714 struct eigrp_prefix_descriptor
*pe
;
716 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
)) {
717 if (iface
!= exception
) {
718 eigrp_update_send(iface
);
722 for (ALL_LIST_ELEMENTS(eigrp
->topology_changes_internalIPV4
, node2
,
724 if (pe
->req_action
& EIGRP_FSM_NEED_UPDATE
) {
725 pe
->req_action
&= ~EIGRP_FSM_NEED_UPDATE
;
726 listnode_delete(eigrp
->topology_changes_internalIPV4
,
733 * @fn eigrp_update_send_GR_part
735 * @param[in] nbr contains neighbor who would receive
742 * Function used for sending Graceful restart Update packet
743 * and if there are multiple chunks, send only one of them.
744 * It is called from thread. Do not call it directly.
746 * Uses nbr_gr_packet_type from neighbor.
748 static void eigrp_update_send_GR_part(struct eigrp_neighbor
*nbr
)
750 struct eigrp_packet
*ep
;
751 uint16_t length
= EIGRP_HEADER_LEN
;
752 struct eigrp_prefix_descriptor
*pe
;
753 struct prefix
*dest_addr
;
754 struct eigrp_interface
*ei
= nbr
->ei
;
755 struct eigrp
*eigrp
= ei
->eigrp
;
756 struct list
*prefixes
;
758 unsigned int send_prefixes
;
759 struct route_node
*rn
;
761 /* get prefixes to send to neighbor */
762 prefixes
= nbr
->nbr_gr_prefixes_send
;
766 /* if there already were last packet chunk, we won't continue */
767 if (nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_LAST
)
770 /* if this is first packet chunk, we need to decide,
771 * if there will be one or more chunks */
772 if (nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_FIRST
) {
773 if (prefixes
->count
<= EIGRP_TLV_MAX_IPv4
) {
774 /* there will be only one chunk */
775 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
777 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
779 /* there will be more chunks */
780 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
;
781 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
784 /* this is not first chunk, and we need to decide,
785 * if there will be more chunks */
786 if (prefixes
->count
<= EIGRP_TLV_MAX_IPv4
) {
787 /* this is last chunk */
788 flags
= EIGRP_EOT_FLAG
;
789 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
791 /* there will be more chunks */
793 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
797 ep
= eigrp_packet_new(EIGRP_PACKET_MTU(ei
->ifp
->mtu
), nbr
);
799 /* Prepare EIGRP Graceful restart UPDATE header */
800 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, eigrp
, ep
->s
, flags
,
801 eigrp
->sequence_number
,
802 nbr
->recv_sequence_number
);
804 // encode Authentication TLV, if needed
805 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
806 && (ei
->params
.auth_keychain
!= NULL
)) {
807 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, ei
);
810 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
818 dest_addr
= pe
->destination
;
820 if (eigrp_update_prefix_apply(eigrp
, ei
, EIGRP_FILTER_OUT
,
822 /* do not send filtered route */
823 zlog_info("Filtered prefix %pI4 won't be sent out.",
824 &dest_addr
->u
.prefix4
);
826 /* sending route which wasn't filtered */
827 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
832 * This makes no sense, Filter out then filter in???
833 * Look into this more - DBS
835 if (eigrp_update_prefix_apply(eigrp
, ei
, EIGRP_FILTER_IN
,
837 /* do not send filtered route */
838 zlog_info("Filtered prefix %pI4 will be removed.",
839 &dest_addr
->u
.prefix4
);
841 /* prepare message for FSM */
842 struct eigrp_fsm_action_message fsm_msg
;
844 struct eigrp_route_descriptor
*entry
=
845 eigrp_route_descriptor_lookup(pe
->entries
, nbr
);
847 fsm_msg
.packet_type
= EIGRP_OPC_UPDATE
;
848 fsm_msg
.eigrp
= eigrp
;
849 fsm_msg
.data_type
= EIGRP_INT
;
850 fsm_msg
.adv_router
= nbr
;
851 fsm_msg
.metrics
= pe
->reported_metric
;
852 /* Set delay to MAX */
853 fsm_msg
.metrics
.delay
= EIGRP_MAX_METRIC
;
854 fsm_msg
.entry
= entry
;
857 /* send message to FSM */
858 eigrp_fsm_event(&fsm_msg
);
861 /* NULL the pointer */
864 /* delete processed prefix from list */
865 listnode_delete(prefixes
, pe
);
867 /* if there are enough prefixes, send packet */
868 if (send_prefixes
>= EIGRP_TLV_MAX_IPv4
)
872 /* compute Auth digest */
873 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
874 && (ei
->params
.auth_keychain
!= NULL
)) {
875 eigrp_make_md5_digest(ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
879 eigrp_packet_checksum(ei
, ep
->s
, length
);
882 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
884 /*This ack number we await from neighbor*/
885 ep
->sequence_number
= eigrp
->sequence_number
;
887 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
889 "Enqueuing Update Init Len [%u] Seq [%u] Dest [%pI4]",
890 ep
->length
, ep
->sequence_number
, &ep
->dst
);
892 /*Put packet to retransmission queue*/
893 eigrp_fifo_push(nbr
->retrans_queue
, ep
);
895 if (nbr
->retrans_queue
->count
== 1) {
896 eigrp_send_packet_reliably(nbr
);
901 * @fn eigrp_update_send_GR_thread
903 * @param[in] thread contains neighbor who would receive
906 * @return int always 0
909 * Function used for sending Graceful restart Update packet
910 * in thread, it is prepared for multiple chunks of packet.
912 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
914 int eigrp_update_send_GR_thread(struct thread
*thread
)
916 struct eigrp_neighbor
*nbr
;
918 /* get argument from thread */
919 nbr
= THREAD_ARG(thread
);
920 /* remove this thread pointer */
921 nbr
->t_nbr_send_gr
= NULL
;
923 /* if there is packet waiting in queue,
924 * schedule this thread again with small delay */
925 if (nbr
->retrans_queue
->count
> 0) {
926 nbr
->t_nbr_send_gr
= NULL
;
927 thread_add_timer_msec(master
, eigrp_update_send_GR_thread
, nbr
,
928 10, &nbr
->t_nbr_send_gr
);
932 /* send GR EIGRP packet chunk */
933 eigrp_update_send_GR_part(nbr
);
935 /* if it wasn't last chunk, schedule this thread again */
936 if (nbr
->nbr_gr_packet_type
!= EIGRP_PACKET_PART_LAST
) {
937 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
938 nbr
->t_nbr_send_gr
= NULL
;
945 * @fn eigrp_update_send_GR
947 * @param[in] nbr Neighbor who would receive
950 * @param[in] gr_type Who executed Graceful restart
951 * @param[in] vty Virtual terminal for log output
956 * Function used for sending Graceful restart Update packet:
957 * Creates Update packet with INIT, RS, EOT flags and include
958 * all route except those filtered
960 void eigrp_update_send_GR(struct eigrp_neighbor
*nbr
, enum GR_type gr_type
,
963 struct eigrp_prefix_descriptor
*pe2
;
964 struct list
*prefixes
;
965 struct route_node
*rn
;
966 struct eigrp_interface
*ei
= nbr
->ei
;
967 struct eigrp
*eigrp
= ei
->eigrp
;
969 if (gr_type
== EIGRP_GR_FILTER
) {
970 /* function was called after applying filtration */
972 "Neighbor %pI4 (%s) is resync: route configuration changed",
974 ifindex2ifname(ei
->ifp
->ifindex
, eigrp
->vrf_id
));
975 } else if (gr_type
== EIGRP_GR_MANUAL
) {
976 /* Graceful restart was called manually */
977 zlog_info("Neighbor %pI4 (%s) is resync: manually cleared",
979 ifindex2ifname(ei
->ifp
->ifindex
, eigrp
->vrf_id
));
982 vty_time_print(vty
, 0);
984 "Neighbor %pI4 (%s) is resync: manually cleared\n",
986 ifindex2ifname(ei
->ifp
->ifindex
,
991 prefixes
= list_new();
992 /* add all prefixes from topology table to list */
993 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
998 listnode_add(prefixes
, pe2
);
1001 /* save prefixes to neighbor */
1002 nbr
->nbr_gr_prefixes_send
= prefixes
;
1003 /* indicate, that this is first GR Update packet chunk */
1004 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_FIRST
;
1005 /* execute packet sending in thread */
1006 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
1007 nbr
->t_nbr_send_gr
= NULL
;
1011 * @fn eigrp_update_send_interface_GR
1013 * @param[in] ei Interface to neighbors of which
1017 * @param[in] gr_type Who executed Graceful restart
1018 * @param[in] vty Virtual terminal for log output
1023 * Function used for sending Graceful restart Update packet
1024 * to all neighbors on specified interface.
1026 void eigrp_update_send_interface_GR(struct eigrp_interface
*ei
,
1027 enum GR_type gr_type
, struct vty
*vty
)
1029 struct listnode
*node
;
1030 struct eigrp_neighbor
*nbr
;
1032 /* iterate over all neighbors on eigrp interface */
1033 for (ALL_LIST_ELEMENTS_RO(ei
->nbrs
, node
, nbr
)) {
1034 /* send GR to neighbor */
1035 eigrp_update_send_GR(nbr
, gr_type
, vty
);
1040 * @fn eigrp_update_send_process_GR
1042 * @param[in] eigrp EIGRP process
1043 * @param[in] gr_type Who executed Graceful restart
1044 * @param[in] vty Virtual terminal for log output
1049 * Function used for sending Graceful restart Update packet
1050 * to all neighbors in eigrp process.
1052 void eigrp_update_send_process_GR(struct eigrp
*eigrp
, enum GR_type gr_type
,
1055 struct listnode
*node
;
1056 struct eigrp_interface
*ei
;
1058 /* iterate over all eigrp interfaces */
1059 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, ei
)) {
1060 /* send GR to all neighbors on interface */
1061 eigrp_update_send_interface_GR(ei
, gr_type
, vty
);