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
76 * Function is used for removing received prefix
77 * from list of neighbor prefixes
79 static void remove_received_prefix_gr(struct list
*nbr_prefixes
,
80 struct eigrp_prefix_entry
*recv_prefix
)
82 struct listnode
*node1
, *node11
;
83 struct eigrp_prefix_entry
*prefix
= NULL
;
85 /* iterate over all prefixes in list */
86 for (ALL_LIST_ELEMENTS(nbr_prefixes
, node1
, node11
, prefix
)) {
87 /* remove prefix from list if found */
88 if (prefix
== recv_prefix
) {
89 listnode_delete(nbr_prefixes
, prefix
);
95 * @fn eigrp_update_receive_GR_ask
97 * @param[in] eigrp EIGRP process
98 * @param[in] nbr Neighbor update of who we
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.
109 static void eigrp_update_receive_GR_ask(struct eigrp
*eigrp
,
110 struct eigrp_neighbor
*nbr
,
111 struct list
*nbr_prefixes
)
113 struct listnode
*node1
;
114 struct eigrp_prefix_entry
*prefix
;
115 struct TLV_IPv4_Internal_type
*tlv_max
;
117 /* iterate over all prefixes which weren't advertised by neighbor */
118 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
162 void eigrp_update_receive(struct eigrp
*eigrp
, struct ip
*iph
,
163 struct eigrp_header
*eigrph
, struct stream
*s
,
164 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
) {
196 graceful_restart
= 0;
197 graceful_restart_final
= 0;
198 if ((nbr
->recv_sequence_number
) == (ntohl(eigrph
->sequence
)))
201 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
202 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
204 "Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]",
206 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
),
207 inet_ntoa(nbr
->src
), nbr
->recv_sequence_number
, flags
);
210 if ((flags
== (EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
+ EIGRP_EOT_FLAG
))
212 /* Graceful restart Update received with all routes */
214 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
216 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
218 /* get all prefixes from neighbor from topology table */
219 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
220 graceful_restart
= 1;
221 graceful_restart_final
= 1;
222 } else if ((flags
== (EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
)) && (!same
)) {
223 /* Graceful restart Update received, routes also in next packet
226 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
228 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
230 /* get all prefixes from neighbor from topology table */
231 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
232 /* save prefixes to neighbor for later use */
233 nbr
->nbr_gr_prefixes
= nbr_prefixes
;
234 graceful_restart
= 1;
235 graceful_restart_final
= 0;
236 } else if ((flags
== (EIGRP_EOT_FLAG
)) && (!same
)) {
237 /* If there was INIT+RS Update packet before,
238 * consider this as GR EOT */
240 if (nbr
->nbr_gr_prefixes
!= NULL
) {
241 /* this is final packet of GR */
242 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
243 nbr
->nbr_gr_prefixes
= NULL
;
245 graceful_restart
= 1;
246 graceful_restart_final
= 1;
249 } else if ((flags
== (0)) && (!same
)) {
250 /* If there was INIT+RS Update packet before,
251 * consider this as GR not final packet */
253 if (nbr
->nbr_gr_prefixes
!= NULL
) {
254 /* this is GR not final route packet */
255 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
257 graceful_restart
= 1;
258 graceful_restart_final
= 0;
261 } else if ((flags
& EIGRP_INIT_FLAG
)
262 && (!same
)) { /* When in pending state, send INIT update only
264 already sent before (only if init_sequence
266 if ((nbr
->state
== EIGRP_NEIGHBOR_PENDING
)
267 && (nbr
->init_sequence_number
== 0))
268 eigrp_update_send_init(nbr
);
270 if (nbr
->state
== EIGRP_NEIGHBOR_UP
) {
271 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
272 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
, nbr
);
273 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
274 zlog_info("Neighbor %s (%s) is down: peer restarted",
276 ifindex2ifname(nbr
->ei
->ifp
->ifindex
,
278 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_PENDING
);
279 zlog_info("Neighbor %s (%s) is pending: new adjacency",
281 ifindex2ifname(nbr
->ei
->ifp
->ifindex
,
283 eigrp_update_send_init(nbr
);
287 /*If there is topology information*/
288 while (s
->endp
> s
->getp
) {
289 type
= stream_getw(s
);
290 if (type
== EIGRP_TLV_IPv4_INT
) {
291 struct prefix_ipv4 dest_addr
;
293 stream_set_getp(s
, s
->getp
- sizeof(u_int16_t
));
295 tlv
= eigrp_read_ipv4_tlv(s
);
297 /*searching if destination exists */
298 dest_addr
.family
= AF_INET
;
299 dest_addr
.prefix
= tlv
->destination
;
300 dest_addr
.prefixlen
= tlv
->prefix_length
;
301 struct eigrp_prefix_entry
*dest
=
302 eigrp_topology_table_lookup_ipv4(
303 eigrp
->topology_table
, &dest_addr
);
305 /*if exists it comes to DUAL*/
307 /* remove received prefix from neighbor prefix
309 if (graceful_restart
)
310 remove_received_prefix_gr(nbr_prefixes
,
313 struct eigrp_fsm_action_message
*msg
;
314 msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
316 eigrp_fsm_action_message
));
317 struct eigrp_neighbor_entry
*entry
=
318 eigrp_prefix_entry_lookup(dest
->entries
,
321 msg
->packet_type
= EIGRP_OPC_UPDATE
;
323 msg
->data_type
= EIGRP_TLV_IPv4_INT
;
324 msg
->adv_router
= nbr
;
325 msg
->data
.ipv4_int_type
= tlv
;
328 int event
= eigrp_get_fsm_event(msg
);
329 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();
336 (struct prefix
*)pe
->destination_ipv4
,
337 (struct prefix
*)&dest_addr
);
339 pe
->state
= EIGRP_FSM_STATE_PASSIVE
;
340 pe
->nt
= EIGRP_TOPOLOGY_TYPE_REMOTE
;
342 ne
= eigrp_neighbor_entry_new();
344 ne
->adv_router
= nbr
;
345 ne
->reported_metric
= tlv
->metric
;
346 ne
->reported_distance
= eigrp_calculate_metrics(
353 * Check if there is any access-list on
354 * interface (IN direction)
355 * and set distance to max
357 alist
= ei
->list
[EIGRP_FILTER_IN
];
359 /* Check if access-list fits */
361 && access_list_apply(
363 (struct prefix
*)&dest_addr
)
365 /* If yes, set reported metric to Max */
366 ne
->reported_metric
.delay
=
370 eigrp_calculate_total_metrics(
374 plist
= e
->prefix
[EIGRP_FILTER_IN
];
376 /* Check if prefix-list fits */
378 && prefix_list_apply(
380 (struct prefix
*)&dest_addr
)
382 /* If yes, set reported metric to Max */
383 ne
->reported_metric
.delay
=
387 /*Get access-list from current interface */
388 alist
= ei
->list
[EIGRP_FILTER_IN
];
390 /* Check if access-list fits */
392 && access_list_apply(
394 (struct prefix
*)&dest_addr
)
396 /* If yes, set reported metric to Max */
397 ne
->reported_metric
.delay
=
401 plist
= ei
->prefix
[EIGRP_FILTER_IN
];
403 /* Check if prefix-list fits */
405 && prefix_list_apply(
407 (struct prefix
*)&dest_addr
)
409 /* If yes, set reported metric to Max */
410 ne
->reported_metric
.delay
=
417 ne
->distance
= eigrp_calculate_total_metrics(
420 pe
->fdistance
= pe
->distance
= pe
->rdistance
=
423 ne
->flags
= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG
;
425 eigrp_prefix_entry_add(eigrp
->topology_table
,
427 eigrp_neighbor_entry_add(pe
, ne
);
428 pe
->distance
= pe
->fdistance
= pe
->rdistance
=
430 pe
->reported_metric
= ne
->total_metric
;
431 eigrp_topology_update_node_flags(pe
);
433 pe
->req_action
|= EIGRP_FSM_NEED_UPDATE
;
435 eigrp
->topology_changes_internalIPV4
,
438 eigrp_IPv4_InternalTLV_free(tlv
);
442 /* ask about prefixes not present in GR update,
443 * if this is final GR packet */
444 if (graceful_restart_final
) {
445 eigrp_update_receive_GR_ask(eigrp
, nbr
, nbr_prefixes
);
449 * We don't need to send separate Ack for INIT Update. INIT will be
450 * acked in EOT Update.
452 if ((nbr
->state
== EIGRP_NEIGHBOR_UP
) && !(flags
== EIGRP_INIT_FLAG
)) {
453 eigrp_hello_send_ack(nbr
);
456 eigrp_query_send_all(eigrp
);
457 eigrp_update_send_all(eigrp
, ei
);
460 /*send EIGRP Update packet*/
461 void eigrp_update_send_init(struct eigrp_neighbor
*nbr
)
463 struct eigrp_packet
*ep
;
464 u_int16_t length
= EIGRP_HEADER_LEN
;
466 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
468 /* Prepare EIGRP INIT UPDATE header */
469 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
470 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
471 nbr
->ei
->eigrp
->sequence_number
,
472 nbr
->recv_sequence_number
);
474 eigrp_packet_header_init(
475 EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
, EIGRP_INIT_FLAG
,
476 nbr
->ei
->eigrp
->sequence_number
, nbr
->recv_sequence_number
);
478 // encode Authentication TLV, if needed
479 if ((IF_DEF_PARAMS(nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
)
480 && (IF_DEF_PARAMS(nbr
->ei
->ifp
)->auth_keychain
!= NULL
)) {
481 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, nbr
->ei
);
482 eigrp_make_md5_digest(nbr
->ei
, ep
->s
,
483 EIGRP_AUTH_UPDATE_INIT_FLAG
);
487 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
490 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
492 /*This ack number we await from neighbor*/
493 nbr
->init_sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
494 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
495 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
496 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
497 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
499 /*Put packet to retransmission queue*/
500 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
502 if (nbr
->retrans_queue
->count
== 1) {
503 eigrp_send_packet_reliably(nbr
);
507 static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor
*nbr
,
508 struct eigrp_packet
*ep
,
512 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
513 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
)) {
514 eigrp_make_md5_digest(nbr
->ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
518 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
521 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
523 /*This ack number we await from neighbor*/
524 ep
->sequence_number
= seq_no
;
526 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
527 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
528 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
530 /*Put packet to retransmission queue*/
531 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
534 void eigrp_update_send_EOT(struct eigrp_neighbor
*nbr
)
536 struct eigrp_packet
*ep
;
537 u_int16_t length
= EIGRP_HEADER_LEN
;
538 struct eigrp_neighbor_entry
*te
;
539 struct eigrp_prefix_entry
*pe
;
540 struct listnode
*node
, *node2
, *nnode
, *nnode2
;
541 struct access_list
*alist
;
542 struct prefix_list
*plist
;
543 struct access_list
*alist_i
;
544 struct prefix_list
*plist_i
;
546 struct prefix_ipv4
*dest_addr
;
547 u_int32_t seq_no
= nbr
->ei
->eigrp
->sequence_number
;
549 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
551 /* Prepare EIGRP EOT UPDATE header */
552 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
, EIGRP_EOT_FLAG
,
554 nbr
->recv_sequence_number
);
556 // encode Authentication TLV, if needed
557 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
558 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
)) {
559 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,nbr
->ei
);
562 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node
, nnode
, pe
)) {
563 for (ALL_LIST_ELEMENTS(pe
->entries
, node2
, nnode2
, te
)) {
564 if ((te
->ei
== nbr
->ei
)
565 && (te
->prefix
->nt
== EIGRP_TOPOLOGY_TYPE_REMOTE
))
568 if ((length
+ 0x001D) > (u_int16_t
)nbr
->ei
->ifp
->mtu
) {
569 eigrp_update_place_on_nbr_queue (nbr
, ep
, seq_no
, length
);
570 eigrp_send_packet_reliably(nbr
);
573 length
= EIGRP_HEADER_LEN
;
574 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
575 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
, EIGRP_EOT_FLAG
,
576 seq_no
, nbr
->recv_sequence_number
);
578 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
579 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
581 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,nbr
->ei
);
584 /* Get destination address from prefix */
585 dest_addr
= pe
->destination_ipv4
;
590 //TODO: Work in progress
591 /* get list from eigrp process */
593 /* Get access-lists and prefix-lists from process and interface */
594 alist
= e
->list
[EIGRP_FILTER_OUT
];
595 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
596 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_OUT
];
597 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_OUT
];
599 /* Check if any list fits */
601 && access_list_apply (alist
,
602 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
603 (plist
&& prefix_list_apply (plist
,
604 (struct prefix
*) dest_addr
) == PREFIX_DENY
)||
605 (alist_i
&& access_list_apply (alist_i
,
606 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
607 (plist_i
&& prefix_list_apply (plist_i
,
608 (struct prefix
*) dest_addr
) == PREFIX_DENY
)) {
609 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
612 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
617 eigrp_update_place_on_nbr_queue (nbr
, ep
, seq_no
, length
);
618 eigrp_send_packet_reliably(nbr
);
621 void eigrp_update_send(struct eigrp_interface
*ei
)
623 struct eigrp_packet
*ep
;
624 struct listnode
*node
, *nnode
;
625 struct eigrp_neighbor
*nbr
;
626 struct eigrp_prefix_entry
*pe
;
628 struct access_list
*alist
;
629 struct prefix_list
*plist
;
630 struct access_list
*alist_i
;
631 struct prefix_list
*plist_i
;
633 struct prefix_ipv4
*dest_addr
;
634 bool packet_sent
= false;
636 u_int16_t length
= EIGRP_HEADER_LEN
;
638 ep
= eigrp_packet_new(ei
->ifp
->mtu
);
640 /* Prepare EIGRP INIT UPDATE header */
641 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, ei
, ep
->s
, 0,
642 ei
->eigrp
->sequence_number
, 0);
644 // encode Authentication TLV, if needed
645 if ((IF_DEF_PARAMS(ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
)
646 && (IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
!= NULL
)) {
647 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, ei
);
651 for (ALL_LIST_ELEMENTS(ei
->eigrp
->topology_changes_internalIPV4
, node
,
653 if (pe
->req_action
& EIGRP_FSM_NEED_UPDATE
) {
654 /* Get destination address from prefix */
655 dest_addr
= pe
->destination_ipv4
;
660 // TODO: Work in progress
661 /* get list from eigrp process */
663 /* Get access-lists and prefix-lists from process and
665 alist
= e
->list
[EIGRP_FILTER_OUT
];
666 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
667 alist_i
= ei
->list
[EIGRP_FILTER_OUT
];
668 plist_i
= ei
->prefix
[EIGRP_FILTER_OUT
];
670 /* Check if any list fits */
672 && access_list_apply(alist
,
673 (struct prefix
*)dest_addr
)
676 && prefix_list_apply(plist
,
677 (struct prefix
*)dest_addr
)
680 && access_list_apply(alist_i
,
681 (struct prefix
*)dest_addr
)
684 && prefix_list_apply(plist_i
,
685 (struct prefix
*)dest_addr
)
687 zlog_info("PROC OUT: Skipping");
688 // pe->reported_metric.delay = EIGRP_MAX_METRIC;
689 zlog_info("PROC OUT Prefix: %s",
690 inet_ntoa(dest_addr
->prefix
));
693 zlog_info("PROC OUT: NENastavujem metriku ");
694 length
+= eigrp_add_internalTLV_to_stream(ep
->s
,
702 /* NULL the pointer */
708 eigrp_packet_free(ep
);
712 if ((IF_DEF_PARAMS(ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
)
713 && (IF_DEF_PARAMS(ei
->ifp
)->auth_keychain
!= NULL
)) {
714 eigrp_make_md5_digest(ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
718 eigrp_packet_checksum(ei
, ep
->s
, length
);
721 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
723 /*This ack number we await from neighbor*/
724 ep
->sequence_number
= ei
->eigrp
->sequence_number
;
726 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
727 zlog_debug("Enqueuing Update length[%u] Seq [%u]", length
,
728 ep
->sequence_number
);
730 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node
, nnode
, nbr
)) {
731 if (nbr
->state
== EIGRP_NEIGHBOR_UP
) {
733 /*Put packet to retransmission queue*/
734 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
736 if (nbr
->retrans_queue
->count
== 1) {
737 eigrp_send_packet_reliably(nbr
);
743 eigrp_packet_free(ep
);
746 void eigrp_update_send_all(struct eigrp
*eigrp
,
747 struct eigrp_interface
*exception
)
749 struct eigrp_interface
*iface
;
750 struct listnode
*node
, *node2
, *nnode2
;
751 struct eigrp_prefix_entry
*pe
;
753 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
)) {
754 if (iface
!= exception
) {
755 eigrp_update_send(iface
);
759 for (ALL_LIST_ELEMENTS(eigrp
->topology_changes_internalIPV4
, node2
,
761 if (pe
->req_action
& EIGRP_FSM_NEED_UPDATE
) {
762 pe
->req_action
&= ~EIGRP_FSM_NEED_UPDATE
;
763 listnode_delete(eigrp
->topology_changes_internalIPV4
,
765 zlog_debug("UPDATE COUNT: %d",
766 eigrp
->topology_changes_internalIPV4
->count
);
772 * @fn eigrp_update_send_GR_part
774 * @param[in] nbr contains neighbor who would receive Graceful
780 * Function used for sending Graceful restart Update packet
781 * and if there are multiple chunks, send only one of them.
782 * It is called from thread. Do not call it directly.
784 * Uses nbr_gr_packet_type from neighbor.
786 static void eigrp_update_send_GR_part(struct eigrp_neighbor
*nbr
)
788 struct eigrp_packet
*ep
;
789 u_int16_t length
= EIGRP_HEADER_LEN
;
790 struct listnode
*node
, *nnode
;
791 struct eigrp_prefix_entry
*pe
;
792 struct prefix_ipv4
*dest_addr
;
794 struct access_list
*alist
, *alist_i
;
795 struct prefix_list
*plist
, *plist_i
;
796 struct list
*prefixes
;
798 unsigned int send_prefixes
;
799 struct TLV_IPv4_Internal_type
*tlv_max
;
801 /* get prefixes to send to neighbor */
802 prefixes
= nbr
->nbr_gr_prefixes_send
;
805 length
= EIGRP_HEADER_LEN
;
807 /* if there already were last packet chunk, we won't continue */
808 if (nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_LAST
)
811 /* if this is first packet chunk, we need to decide,
812 * if there will be one or more chunks */
813 if (nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_FIRST
) {
814 if (prefixes
->count
<= EIGRP_TLV_MAX_IPv4
) {
815 /* there will be only one chunk */
816 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
818 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
820 /* there will be more chunks */
821 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
;
822 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
825 /* this is not first chunk, and we need to decide,
826 * if there will be more chunks */
827 if (prefixes
->count
<= EIGRP_TLV_MAX_IPv4
) {
828 /* this is last chunk */
829 flags
= EIGRP_EOT_FLAG
;
830 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
832 /* there will be more chunks */
834 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
838 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
840 /* Prepare EIGRP Graceful restart UPDATE header */
841 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
, flags
,
842 nbr
->ei
->eigrp
->sequence_number
,
843 nbr
->recv_sequence_number
);
845 // encode Authentication TLV, if needed
846 if ((IF_DEF_PARAMS(nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
)
847 && (IF_DEF_PARAMS(nbr
->ei
->ifp
)->auth_keychain
!= NULL
)) {
848 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
, nbr
->ei
);
851 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node
, nnode
,
856 dest_addr
= pe
->destination_ipv4
;
857 /* get list from eigrp process */
859 /* Get access-lists and prefix-lists from process and interface
861 alist
= e
->list
[EIGRP_FILTER_OUT
];
862 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
863 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_OUT
];
864 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_OUT
];
866 /* Check if any list fits */
868 && access_list_apply(alist
, (struct prefix
*)dest_addr
)
871 && prefix_list_apply(plist
, (struct prefix
*)dest_addr
)
874 && access_list_apply(alist_i
,
875 (struct prefix
*)dest_addr
)
878 && prefix_list_apply(plist_i
,
879 (struct prefix
*)dest_addr
)
881 /* do not send filtered route */
882 zlog_info("Filtered prefix %s won't be sent out.",
883 inet_ntoa(dest_addr
->prefix
));
885 /* sending route which wasn't filtered */
886 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
890 alist
= e
->list
[EIGRP_FILTER_IN
];
891 plist
= e
->prefix
[EIGRP_FILTER_IN
];
892 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_IN
];
893 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_IN
];
895 /* Check if any list fits */
897 && access_list_apply(alist
, (struct prefix
*)dest_addr
)
900 && prefix_list_apply(plist
, (struct prefix
*)dest_addr
)
903 && access_list_apply(alist_i
,
904 (struct prefix
*)dest_addr
)
907 && prefix_list_apply(plist_i
,
908 (struct prefix
*)dest_addr
)
910 /* do not send filtered route */
911 zlog_info("Filtered prefix %s will be removed.",
912 inet_ntoa(dest_addr
->prefix
));
914 tlv_max
= eigrp_IPv4_InternalTLV_new();
915 tlv_max
->type
= EIGRP_TLV_IPv4_INT
;
916 tlv_max
->length
= 28U;
917 tlv_max
->metric
= pe
->reported_metric
;
918 /* set delay to MAX */
919 tlv_max
->metric
.delay
= EIGRP_MAX_METRIC
;
920 tlv_max
->destination
= pe
->destination_ipv4
->prefix
;
921 tlv_max
->prefix_length
=
922 pe
->destination_ipv4
->prefixlen
;
924 /* prepare message for FSM */
925 struct eigrp_fsm_action_message
*fsm_msg
;
928 sizeof(struct eigrp_fsm_action_message
));
930 struct eigrp_neighbor_entry
*entry
=
931 eigrp_prefix_entry_lookup(pe
->entries
, nbr
);
933 fsm_msg
->packet_type
= EIGRP_OPC_UPDATE
;
935 fsm_msg
->data_type
= EIGRP_TLV_IPv4_INT
;
936 fsm_msg
->adv_router
= nbr
;
937 fsm_msg
->data
.ipv4_int_type
= tlv_max
;
938 fsm_msg
->entry
= entry
;
939 fsm_msg
->prefix
= pe
;
941 /* send message to FSM */
942 int event
= eigrp_get_fsm_event(fsm_msg
);
943 eigrp_fsm_event(fsm_msg
, event
);
945 /* free memory used by TLV */
946 eigrp_IPv4_InternalTLV_free(tlv_max
);
952 /* NULL the pointer */
955 /* delete processed prefix from list */
956 listnode_delete(prefixes
, pe
);
958 /* if there are enough prefixes, send packet */
959 if (send_prefixes
>= EIGRP_TLV_MAX_IPv4
)
963 /* compute Auth digest */
964 if ((IF_DEF_PARAMS(nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
)
965 && (IF_DEF_PARAMS(nbr
->ei
->ifp
)->auth_keychain
!= NULL
)) {
966 eigrp_make_md5_digest(nbr
->ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
970 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
973 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
975 /*This ack number we await from neighbor*/
976 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
978 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
979 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
980 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
982 /*Put packet to retransmission queue*/
983 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
985 if (nbr
->retrans_queue
->count
== 1) {
986 eigrp_send_packet_reliably(nbr
);
991 * @fn eigrp_update_send_GR_thread
993 * @param[in] thread contains neighbor who would receive
996 * @return int always 0
999 * Function used for sending Graceful restart Update packet
1000 * in thread, it is prepared for multiple chunks of packet.
1002 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
1004 int eigrp_update_send_GR_thread(struct thread
*thread
)
1006 struct eigrp_neighbor
*nbr
;
1008 /* get argument from thread */
1009 nbr
= THREAD_ARG(thread
);
1010 /* remove this thread pointer */
1011 nbr
->t_nbr_send_gr
= NULL
;
1013 /* if there is packet waiting in queue,
1014 * schedule this thread again with small delay */
1015 if (nbr
->retrans_queue
->count
> 0) {
1016 nbr
->t_nbr_send_gr
= NULL
;
1017 thread_add_timer_msec(master
, eigrp_update_send_GR_thread
, nbr
,
1018 10, &nbr
->t_nbr_send_gr
);
1022 /* send GR EIGRP packet chunk */
1023 eigrp_update_send_GR_part(nbr
);
1025 /* if it wasn't last chunk, schedule this thread again */
1026 if (nbr
->nbr_gr_packet_type
!= EIGRP_PACKET_PART_LAST
) {
1027 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
1028 nbr
->t_nbr_send_gr
= NULL
;
1035 * @fn eigrp_update_send_GR
1037 * @param[in] nbr Neighbor who would receive Graceful
1039 * @param[in] gr_type Who executed Graceful restart
1040 * @param[in] vty Virtual terminal for log output
1045 * Function used for sending Graceful restart Update packet:
1046 * Creates Update packet with INIT, RS, EOT flags and include
1047 * all route except those filtered
1049 void eigrp_update_send_GR(struct eigrp_neighbor
*nbr
, enum GR_type gr_type
,
1052 struct eigrp_prefix_entry
*pe2
;
1053 struct listnode
*node2
, *nnode2
;
1054 struct list
*prefixes
;
1056 if (gr_type
== EIGRP_GR_FILTER
) {
1057 /* function was called after applying filtration */
1059 "Neighbor %s (%s) is resync: route configuration changed",
1060 inet_ntoa(nbr
->src
),
1061 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
1062 } else if (gr_type
== EIGRP_GR_MANUAL
) {
1063 /* Graceful restart was called manually */
1064 zlog_info("Neighbor %s (%s) is resync: manually cleared",
1065 inet_ntoa(nbr
->src
),
1066 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
1069 vty_time_print(vty
, 0);
1071 "Neighbor %s (%s) is resync: manually cleared\n",
1072 inet_ntoa(nbr
->src
),
1073 ifindex2ifname(nbr
->ei
->ifp
->ifindex
,
1078 prefixes
= list_new();
1079 /* add all prefixes from topology table to list */
1080 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node2
, nnode2
,
1082 listnode_add(prefixes
, pe2
);
1085 /* save prefixes to neighbor */
1086 nbr
->nbr_gr_prefixes_send
= prefixes
;
1087 /* indicate, that this is first GR Update packet chunk */
1088 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_FIRST
;
1089 /* execute packet sending in thread */
1090 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
1091 nbr
->t_nbr_send_gr
= NULL
;
1095 * @fn eigrp_update_send_interface_GR
1097 * @param[in] ei Interface to neighbors of which the GR
1099 * @param[in] gr_type Who executed Graceful restart
1100 * @param[in] vty Virtual terminal for log output
1105 * Function used for sending Graceful restart Update packet
1106 * to all neighbors on specified interface.
1108 void eigrp_update_send_interface_GR(struct eigrp_interface
*ei
,
1109 enum GR_type gr_type
, struct vty
*vty
)
1111 struct listnode
*node
;
1112 struct eigrp_neighbor
*nbr
;
1114 /* iterate over all neighbors on eigrp interface */
1115 for (ALL_LIST_ELEMENTS_RO(ei
->nbrs
, node
, nbr
)) {
1116 /* send GR to neighbor */
1117 eigrp_update_send_GR(nbr
, gr_type
, vty
);
1122 * @fn eigrp_update_send_process_GR
1124 * @param[in] eigrp EIGRP process
1125 * @param[in] gr_type Who executed Graceful restart
1126 * @param[in] vty Virtual terminal for log output
1131 * Function used for sending Graceful restart Update packet
1132 * to all neighbors in eigrp process.
1134 void eigrp_update_send_process_GR(struct eigrp
*eigrp
, enum GR_type gr_type
,
1137 struct listnode
*node
;
1138 struct eigrp_interface
*ei
;
1140 /* iterate over all eigrp interfaces */
1141 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, ei
)) {
1142 /* send GR to all neighbors on interface */
1143 eigrp_update_send_interface_GR(ei
, gr_type
, vty
);