2 * EIGRP Sending and Receiving EIGRP Update Packets.
3 * Copyright (C) 2013-2016
15 * This file is part of GNU Zebra.
17 * GNU Zebra is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2, or (at your option) any
22 * GNU Zebra is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
27 * You should have received a copy of the GNU General Public License along
28 * with this program; see the file COPYING; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
40 #include "sockunion.h"
48 #include "plist_int.h"
52 #include "eigrpd/eigrp_structs.h"
53 #include "eigrpd/eigrpd.h"
54 #include "eigrpd/eigrp_interface.h"
55 #include "eigrpd/eigrp_neighbor.h"
56 #include "eigrpd/eigrp_packet.h"
57 #include "eigrpd/eigrp_zebra.h"
58 #include "eigrpd/eigrp_vty.h"
59 #include "eigrpd/eigrp_dump.h"
60 #include "eigrpd/eigrp_macros.h"
61 #include "eigrpd/eigrp_topology.h"
62 #include "eigrpd/eigrp_fsm.h"
63 #include "eigrpd/eigrp_network.h"
64 #include "eigrpd/eigrp_memory.h"
67 * @fn remove_received_prefix_gr
69 * @param[in] nbr_prefixes List of neighbor prefixes
70 * @param[in] recv_prefix Prefix which needs to be removed from list
75 * Function is used for removing received prefix
76 * from list of neighbor prefixes
79 remove_received_prefix_gr (struct list
*nbr_prefixes
, struct eigrp_prefix_entry
*recv_prefix
)
81 struct listnode
*node1
, *node11
;
82 struct eigrp_prefix_entry
*prefix
= NULL
;
84 /* iterate over all prefixes in list */
85 for (ALL_LIST_ELEMENTS(nbr_prefixes
, node1
, node11
, prefix
))
87 /* remove prefix from list if found */
88 if (prefix
== recv_prefix
)
90 listnode_delete(nbr_prefixes
, prefix
);
96 * @fn eigrp_update_receive_GR_ask
98 * @param[in] eigrp EIGRP process
99 * @param[in] nbr Neighbor update of who we received
100 * @param[in] nbr_prefixes Prefixes which weren't advertised
105 * Function is used for notifying FSM about prefixes which
106 * weren't advertised by neighbor:
107 * We will send message to FSM with prefix delay set to infinity.
110 eigrp_update_receive_GR_ask (struct eigrp
*eigrp
, struct eigrp_neighbor
*nbr
, struct list
*nbr_prefixes
)
112 struct listnode
*node1
;
113 struct eigrp_prefix_entry
*prefix
;
114 struct TLV_IPv4_Internal_type
*tlv_max
;
116 /* iterate over all prefixes which weren't advertised by neighbor */
117 for (ALL_LIST_ELEMENTS_RO(nbr_prefixes
, node1
, prefix
))
119 zlog_debug("GR receive: Neighbor not advertised %s/%d",
120 inet_ntoa(prefix
->destination_ipv4
->prefix
),
121 prefix
->destination_ipv4
->prefixlen
);
123 /* create internal IPv4 TLV with infinite delay */
124 tlv_max
= eigrp_IPv4_InternalTLV_new();
125 tlv_max
->type
= EIGRP_TLV_IPv4_INT
;
126 tlv_max
->length
= 28U;
127 tlv_max
->metric
= prefix
->reported_metric
;
128 /* set delay to MAX */
129 tlv_max
->metric
.delay
= EIGRP_MAX_METRIC
;
130 tlv_max
->destination
= prefix
->destination_ipv4
->prefix
;
131 tlv_max
->prefix_length
= prefix
->destination_ipv4
->prefixlen
;
134 /* prepare message for FSM */
135 struct eigrp_fsm_action_message
*fsm_msg
;
136 fsm_msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
137 sizeof(struct eigrp_fsm_action_message
));
139 struct eigrp_neighbor_entry
*entry
=
140 eigrp_prefix_entry_lookup(prefix
->entries
, nbr
);
142 fsm_msg
->packet_type
= EIGRP_OPC_UPDATE
;
143 fsm_msg
->eigrp
= eigrp
;
144 fsm_msg
->data_type
= EIGRP_TLV_IPv4_INT
;
145 fsm_msg
->adv_router
= nbr
;
146 fsm_msg
->data
.ipv4_int_type
= tlv_max
;
147 fsm_msg
->entry
= entry
;
148 fsm_msg
->prefix
= prefix
;
150 /* send message to FSM */
151 int event
= eigrp_get_fsm_event(fsm_msg
);
152 eigrp_fsm_event(fsm_msg
, event
);
154 /* free memory used by TLV */
155 eigrp_IPv4_InternalTLV_free (tlv_max
);
160 * EIGRP UPDATE read function
163 eigrp_update_receive (struct eigrp
*eigrp
, struct ip
*iph
, struct eigrp_header
*eigrph
,
164 struct stream
* s
, struct eigrp_interface
*ei
, int size
)
166 struct eigrp_neighbor
*nbr
;
167 struct TLV_IPv4_Internal_type
*tlv
;
168 struct eigrp_prefix_entry
*pe
;
169 struct eigrp_neighbor_entry
*ne
;
173 struct access_list
*alist
;
174 struct prefix_list
*plist
;
176 u_char graceful_restart
;
177 u_char graceful_restart_final
;
178 struct list
*nbr_prefixes
= NULL
;
180 /* increment statistics. */
183 /* get neighbor struct */
184 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
186 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
189 flags
= ntohl(eigrph
->flags
);
191 if (flags
& EIGRP_CR_FLAG
)
197 graceful_restart
= 0;
198 graceful_restart_final
= 0;
199 if((nbr
->recv_sequence_number
) == (ntohl(eigrph
->sequence
)))
202 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
203 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
204 zlog_debug("Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]",
205 size
, ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
),
207 nbr
->recv_sequence_number
, flags
);
210 if((flags
== (EIGRP_INIT_FLAG
+EIGRP_RS_FLAG
+EIGRP_EOT_FLAG
)) && (!same
))
212 /* Graceful restart Update received with all routes */
214 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
215 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
217 /* get all prefixes from neighbor from topology table */
218 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
219 graceful_restart
= 1;
220 graceful_restart_final
= 1;
222 else if((flags
== (EIGRP_INIT_FLAG
+EIGRP_RS_FLAG
)) && (!same
))
224 /* Graceful restart Update received, routes also in next packet */
226 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
227 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
229 /* get all prefixes from neighbor from topology table */
230 nbr_prefixes
= eigrp_neighbor_prefixes_lookup(eigrp
, nbr
);
231 /* save prefixes to neighbor for later use */
232 nbr
->nbr_gr_prefixes
= nbr_prefixes
;
233 graceful_restart
= 1;
234 graceful_restart_final
= 0;
236 else if((flags
== (EIGRP_EOT_FLAG
)) && (!same
))
238 /* If there was INIT+RS Update packet before,
239 * consider this as GR EOT */
241 if(nbr
->nbr_gr_prefixes
!= NULL
)
243 /* this is final packet of GR */
244 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
245 nbr
->nbr_gr_prefixes
= NULL
;
247 graceful_restart
= 1;
248 graceful_restart_final
= 1;
252 else if((flags
== (0)) && (!same
))
254 /* If there was INIT+RS Update packet before,
255 * consider this as GR not final packet */
257 if(nbr
->nbr_gr_prefixes
!= NULL
)
259 /* this is GR not final route packet */
260 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
262 graceful_restart
= 1;
263 graceful_restart_final
= 0;
267 else if((flags
& EIGRP_INIT_FLAG
) && (!same
))
268 { /* When in pending state, send INIT update only if it wasn't
269 already sent before (only if init_sequence is 0) */
270 if((nbr
->state
== EIGRP_NEIGHBOR_PENDING
) && (nbr
->init_sequence_number
== 0))
271 eigrp_update_send_init(nbr
);
273 if (nbr
->state
== EIGRP_NEIGHBOR_UP
)
275 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
276 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
,nbr
);
277 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
278 zlog_info("Neighbor %s (%s) is down: peer restarted",
279 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
280 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_PENDING
);
281 zlog_info("Neighbor %s (%s) is pending: new adjacency",
282 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
283 eigrp_update_send_init(nbr
);
287 /*If there is topology information*/
288 while (s
->endp
> s
->getp
)
290 type
= stream_getw(s
);
291 if (type
== EIGRP_TLV_IPv4_INT
)
293 stream_set_getp(s
, s
->getp
- sizeof(u_int16_t
));
295 tlv
= eigrp_read_ipv4_tlv(s
);
297 /*searching if destination exists */
298 struct prefix_ipv4
*dest_addr
;
299 dest_addr
= prefix_ipv4_new();
300 dest_addr
->prefix
= tlv
->destination
;
301 dest_addr
->prefixlen
= tlv
->prefix_length
;
302 struct eigrp_prefix_entry
*dest
=
303 eigrp_topology_table_lookup_ipv4(eigrp
->topology_table
, dest_addr
);
305 /*if exists it comes to DUAL*/
308 /* remove received prefix from neighbor prefix list if in GR */
310 remove_received_prefix_gr(nbr_prefixes
, dest
);
312 struct eigrp_fsm_action_message
*msg
;
313 msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
314 sizeof(struct eigrp_fsm_action_message
));
315 struct eigrp_neighbor_entry
*entry
=
316 eigrp_prefix_entry_lookup(dest
->entries
, nbr
);
318 msg
->packet_type
= EIGRP_OPC_UPDATE
;
320 msg
->data_type
= EIGRP_TLV_IPv4_INT
;
321 msg
->adv_router
= nbr
;
322 msg
->data
.ipv4_int_type
= tlv
;
325 int event
= eigrp_get_fsm_event(msg
);
326 eigrp_fsm_event(msg
, event
);
330 /*Here comes topology information save*/
331 pe
= eigrp_prefix_entry_new();
332 pe
->serno
= eigrp
->serno
;
333 pe
->destination_ipv4
= dest_addr
;
335 pe
->state
= EIGRP_FSM_STATE_PASSIVE
;
336 pe
->nt
= EIGRP_TOPOLOGY_TYPE_REMOTE
;
338 ne
= eigrp_neighbor_entry_new();
340 ne
->adv_router
= nbr
;
341 ne
->reported_metric
= tlv
->metric
;
342 ne
->reported_distance
=
343 eigrp_calculate_metrics(eigrp
,
350 * Check if there is any access-list on interface (IN direction)
351 * and set distance to max
353 alist
= ei
->list
[EIGRP_FILTER_IN
];
356 zlog_info ("ALIST PROC IN: %s", alist
->name
);
358 zlog_info("ALIST je prazdny");
361 /* Check if access-list fits */
362 if (alist
&& access_list_apply (alist
,
363 (struct prefix
*) dest_addr
) == FILTER_DENY
)
365 /* If yes, set reported metric to Max */
366 zlog_info("PROC IN: Nastavujem metriku na MAX");
367 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
368 zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr
->prefix
));
370 zlog_info("PROC IN: NENastavujem metriku ");
371 ne
->distance
= eigrp_calculate_total_metrics(eigrp
, ne
);
374 plist
= e
->prefix
[EIGRP_FILTER_IN
];
377 zlog_info ("PLIST PROC IN: %s", plist
->name
);
379 zlog_info("PLIST PROC IN je prazdny");
382 /* Check if prefix-list fits */
383 if (plist
&& prefix_list_apply (plist
,
384 (struct prefix
*) dest_addr
) == PREFIX_DENY
)
386 /* If yes, set reported metric to Max */
387 zlog_info("PLIST PROC IN: Nastavujem metriku na MAX");
388 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
389 zlog_info("PLIST PROC IN Prefix: %s", inet_ntoa(dest_addr
->prefix
));
391 zlog_info("PLIST PROC IN: NENastavujem metriku ");
394 /*Get access-list from current interface */
395 zlog_info("Checking access_list on interface: %s",ei
->ifp
->name
);
396 alist
= ei
->list
[EIGRP_FILTER_IN
];
398 zlog_info ("ALIST INT IN: %s", alist
->name
);
400 zlog_info("ALIST INT IN je prazdny");
403 /* Check if access-list fits */
404 if (alist
&& access_list_apply (alist
, (struct prefix
*) dest_addr
) == FILTER_DENY
)
406 /* If yes, set reported metric to Max */
407 zlog_info("INT IN: Nastavujem metriku na MAX");
408 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
409 zlog_info("INT IN Prefix: %s", inet_ntoa(dest_addr
->prefix
));
411 zlog_info("INT IN: NENastavujem metriku ");
414 plist
= ei
->prefix
[EIGRP_FILTER_IN
];
417 zlog_info ("PLIST INT IN: %s", plist
->name
);
419 zlog_info("PLIST INT IN je prazdny");
422 /* Check if prefix-list fits */
423 if (plist
&& prefix_list_apply (plist
,
424 (struct prefix
*) dest_addr
) == PREFIX_DENY
)
426 /* If yes, set reported metric to Max */
427 zlog_info("PLIST INT IN: Nastavujem metriku na MAX");
428 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
429 zlog_info("PLIST INT IN Prefix: %s", inet_ntoa(dest_addr
->prefix
));
431 zlog_info("PLIST INT IN: NENastavujem metriku ");
437 ne
->distance
= eigrp_calculate_total_metrics(eigrp
, ne
);
439 zlog_info("<DEBUG PROC IN Distance: %x", ne
->distance
);
440 zlog_info("<DEBUG PROC IN Delay: %x", ne
->total_metric
.delay
);
442 pe
->fdistance
= pe
->distance
= pe
->rdistance
=
445 ne
->flags
= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG
;
447 eigrp_prefix_entry_add(eigrp
->topology_table
, pe
);
448 eigrp_neighbor_entry_add(pe
, ne
);
449 pe
->distance
= pe
->fdistance
= pe
->rdistance
=
451 pe
->reported_metric
= ne
->total_metric
;
452 eigrp_topology_update_node_flags(pe
);
454 pe
->req_action
|= EIGRP_FSM_NEED_UPDATE
;
455 listnode_add(eigrp
->topology_changes_internalIPV4
, pe
);
457 eigrp_IPv4_InternalTLV_free (tlv
);
461 /* ask about prefixes not present in GR update,
462 * if this is final GR packet */
463 if(graceful_restart_final
)
465 eigrp_update_receive_GR_ask(eigrp
, nbr
, nbr_prefixes
);
469 * We don't need to send separate Ack for INIT Update. INIT will be acked in EOT Update.
471 if ((nbr
->state
== EIGRP_NEIGHBOR_UP
) && !(flags
== EIGRP_INIT_FLAG
))
473 eigrp_hello_send_ack(nbr
);
476 eigrp_query_send_all(eigrp
);
477 eigrp_update_send_all(eigrp
, ei
);
480 /*send EIGRP Update packet*/
482 eigrp_update_send_init (struct eigrp_neighbor
*nbr
)
484 struct eigrp_packet
*ep
;
485 u_int16_t length
= EIGRP_HEADER_LEN
;
487 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
489 /* Prepare EIGRP INIT UPDATE header */
490 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
491 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
492 nbr
->ei
->eigrp
->sequence_number
,
493 nbr
->recv_sequence_number
);
495 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
, EIGRP_INIT_FLAG
,
496 nbr
->ei
->eigrp
->sequence_number
,
497 nbr
->recv_sequence_number
);
499 // encode Authentication TLV, if needed
500 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
501 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
503 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,nbr
->ei
);
504 eigrp_make_md5_digest(nbr
->ei
,ep
->s
, EIGRP_AUTH_UPDATE_INIT_FLAG
);
508 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
511 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
513 /*This ack number we await from neighbor*/
514 nbr
->init_sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
515 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
516 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
517 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
518 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
520 /*Put packet to retransmission queue*/
521 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
523 if (nbr
->retrans_queue
->count
== 1)
525 eigrp_send_packet_reliably(nbr
);
530 eigrp_update_send_EOT (struct eigrp_neighbor
*nbr
)
532 struct eigrp_packet
*ep
;
533 // struct eigrp_packet *ep_multicast;
534 u_int16_t length
= EIGRP_HEADER_LEN
;
535 struct eigrp_neighbor_entry
*te
;
536 struct eigrp_prefix_entry
*pe
;
537 struct listnode
*node
, *node2
, *nnode
, *nnode2
;
538 struct access_list
*alist
;
539 struct prefix_list
*plist
;
540 struct access_list
*alist_i
;
541 struct prefix_list
*plist_i
;
543 struct prefix_ipv4
*dest_addr
;
545 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
547 /* Prepare EIGRP EOT UPDATE header */
548 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
, EIGRP_EOT_FLAG
,
549 nbr
->ei
->eigrp
->sequence_number
,
550 nbr
->recv_sequence_number
);
552 // encode Authentication TLV, if needed
553 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) && (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
555 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,nbr
->ei
);
558 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node
, nnode
, pe
))
560 for (ALL_LIST_ELEMENTS(pe
->entries
, node2
, nnode2
, te
))
562 if ((te
->ei
== nbr
->ei
)
563 && (te
->prefix
->nt
== EIGRP_TOPOLOGY_TYPE_REMOTE
))
566 /* Get destination address from prefix */
567 dest_addr
= pe
->destination_ipv4
;
572 //TODO: Work in progress
573 /* get list from eigrp process */
575 /* Get access-lists and prefix-lists from process and interface */
576 alist
= e
->list
[EIGRP_FILTER_OUT
];
577 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
578 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_OUT
];
579 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_OUT
];
581 /* Check if any list fits */
582 if ((alist
&& access_list_apply (alist
,
583 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
584 (plist
&& prefix_list_apply (plist
,
585 (struct prefix
*) dest_addr
) == PREFIX_DENY
)||
586 (alist_i
&& access_list_apply (alist_i
,
587 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
588 (plist_i
&& prefix_list_apply (plist_i
,
589 (struct prefix
*) dest_addr
) == PREFIX_DENY
))
591 zlog_info("PROC OUT EOT: Skipping");
592 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
593 zlog_info("PROC OUT EOT Prefix: %s", inet_ntoa(dest_addr
->prefix
));
596 zlog_info("PROC OUT EOT: NENastavujem metriku ");
597 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
603 /* NULL the pointer */
609 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
610 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
612 eigrp_make_md5_digest(nbr
->ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
616 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
619 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
621 /*This ack number we await from neighbor*/
622 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
624 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
625 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
626 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
628 /*Put packet to retransmission queue*/
629 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
631 if (nbr
->retrans_queue
->count
== 1)
633 eigrp_send_packet_reliably(nbr
);
638 eigrp_update_send (struct eigrp_interface
*ei
)
640 struct eigrp_packet
*ep
;
641 struct listnode
*node
, *nnode
;
642 struct eigrp_neighbor
*nbr
;
643 struct eigrp_prefix_entry
*pe
;
645 struct access_list
*alist
;
646 struct prefix_list
*plist
;
647 struct access_list
*alist_i
;
648 struct prefix_list
*plist_i
;
650 struct prefix_ipv4
*dest_addr
;
652 u_int16_t length
= EIGRP_HEADER_LEN
;
654 ep
= eigrp_packet_new(ei
->ifp
->mtu
);
656 /* Prepare EIGRP INIT UPDATE header */
657 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, ei
, ep
->s
, 0,
658 ei
->eigrp
->sequence_number
, 0);
660 // encode Authentication TLV, if needed
661 if((IF_DEF_PARAMS (ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
662 (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
664 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,ei
);
668 for (ALL_LIST_ELEMENTS(ei
->eigrp
->topology_changes_internalIPV4
, node
, nnode
, pe
))
670 if(pe
->req_action
& EIGRP_FSM_NEED_UPDATE
)
672 /* Get destination address from prefix */
673 dest_addr
= pe
->destination_ipv4
;
678 //TODO: Work in progress
679 /* get list from eigrp process */
681 /* Get access-lists and prefix-lists from process and interface */
682 alist
= e
->list
[EIGRP_FILTER_OUT
];
683 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
684 alist_i
= ei
->list
[EIGRP_FILTER_OUT
];
685 plist_i
= ei
->prefix
[EIGRP_FILTER_OUT
];
687 /* Check if any list fits */
688 if ((alist
&& access_list_apply (alist
,
689 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
690 (plist
&& prefix_list_apply (plist
,
691 (struct prefix
*) dest_addr
) == PREFIX_DENY
)||
692 (alist_i
&& access_list_apply (alist_i
,
693 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
694 (plist_i
&& prefix_list_apply (plist_i
,
695 (struct prefix
*) dest_addr
) == PREFIX_DENY
))
697 zlog_info("PROC OUT: Skipping");
698 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
699 zlog_info("PROC OUT Prefix: %s", inet_ntoa(dest_addr
->prefix
));
702 zlog_info("PROC OUT: NENastavujem metriku ");
703 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
710 /* NULL the pointer */
718 eigrp_packet_free(ep
);
722 if((IF_DEF_PARAMS (ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) && (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
724 eigrp_make_md5_digest(ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
728 eigrp_packet_checksum(ei
, ep
->s
, length
);
731 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
733 /*This ack number we await from neighbor*/
734 ep
->sequence_number
= ei
->eigrp
->sequence_number
;
736 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
737 zlog_debug("Enqueuing Update length[%u] Seq [%u]",
738 length
, ep
->sequence_number
);
740 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node
, nnode
, nbr
))
742 if (nbr
->state
== EIGRP_NEIGHBOR_UP
)
744 /*Put packet to retransmission queue*/
745 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
747 if (nbr
->retrans_queue
->count
== 1)
749 eigrp_send_packet_reliably(nbr
);
756 eigrp_update_send_all (struct eigrp
*eigrp
, struct eigrp_interface
*exception
)
758 struct eigrp_interface
*iface
;
759 struct listnode
*node
, *node2
, *nnode2
;
760 struct eigrp_prefix_entry
*pe
;
762 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
))
764 if (iface
!= exception
)
766 eigrp_update_send(iface
);
770 for (ALL_LIST_ELEMENTS(eigrp
->topology_changes_internalIPV4
, node2
, nnode2
, pe
))
772 if(pe
->req_action
& EIGRP_FSM_NEED_UPDATE
)
774 pe
->req_action
&= ~EIGRP_FSM_NEED_UPDATE
;
775 listnode_delete(eigrp
->topology_changes_internalIPV4
, pe
);
776 zlog_debug("UPDATE COUNT: %d", eigrp
->topology_changes_internalIPV4
->count
);
782 * @fn eigrp_update_send_GR_part
784 * @param[in] nbr contains neighbor who would receive Graceful restart
789 * Function used for sending Graceful restart Update packet
790 * and if there are multiple chunks, send only one of them.
791 * It is called from thread. Do not call it directly.
793 * Uses nbr_gr_packet_type from neighbor.
796 eigrp_update_send_GR_part(struct eigrp_neighbor
*nbr
)
798 struct eigrp_packet
*ep
;
799 u_int16_t length
= EIGRP_HEADER_LEN
;
800 struct listnode
*node
, *nnode
;
801 struct eigrp_prefix_entry
*pe
;
802 struct prefix_ipv4
*dest_addr
;
804 struct access_list
*alist
, *alist_i
;
805 struct prefix_list
*plist
, *plist_i
;
806 struct list
*prefixes
;
808 unsigned int send_prefixes
;
809 struct TLV_IPv4_Internal_type
*tlv_max
;
811 /* get prefixes to send to neighbor */
812 prefixes
= nbr
->nbr_gr_prefixes_send
;
815 length
= EIGRP_HEADER_LEN
;
817 /* if there already were last packet chunk, we won't continue */
818 if(nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_LAST
)
821 /* if this is first packet chunk, we need to decide,
822 * if there will be one or more chunks */
823 if(nbr
->nbr_gr_packet_type
== EIGRP_PACKET_PART_FIRST
)
825 if(prefixes
->count
<= EIGRP_TLV_MAX_IPv4
)
827 /* there will be only one chunk */
828 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
+ EIGRP_EOT_FLAG
;
829 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
833 /* there will be more chunks */
834 flags
= EIGRP_INIT_FLAG
+ EIGRP_RS_FLAG
;
835 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
840 /* this is not first chunk, and we need to decide,
841 * if there will be more chunks */
842 if(prefixes
->count
<= EIGRP_TLV_MAX_IPv4
)
844 /* this is last chunk */
845 flags
= EIGRP_EOT_FLAG
;
846 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_LAST
;
850 /* there will be more chunks */
852 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_NA
;
856 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
858 /* Prepare EIGRP Graceful restart UPDATE header */
859 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
,
861 nbr
->ei
->eigrp
->sequence_number
,
862 nbr
->recv_sequence_number
);
864 // encode Authentication TLV, if needed
865 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
866 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
868 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,nbr
->ei
);
871 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node
, nnode
, pe
))
876 dest_addr
= pe
->destination_ipv4
;
877 /* get list from eigrp process */
879 /* Get access-lists and prefix-lists from process and interface */
880 alist
= e
->list
[EIGRP_FILTER_OUT
];
881 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
882 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_OUT
];
883 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_OUT
];
885 /* Check if any list fits */
886 if ((alist
&& access_list_apply (alist
,
887 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
888 (plist
&& prefix_list_apply (plist
,
889 (struct prefix
*) dest_addr
) == PREFIX_DENY
)||
890 (alist_i
&& access_list_apply (alist_i
,
891 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
892 (plist_i
&& prefix_list_apply (plist_i
,
893 (struct prefix
*) dest_addr
) == PREFIX_DENY
))
895 /* do not send filtered route */
896 zlog_info("Filtered prefix %s won't be sent out.",
897 inet_ntoa(dest_addr
->prefix
));
901 /* sending route which wasn't filtered */
902 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
906 alist
= e
->list
[EIGRP_FILTER_IN
];
907 plist
= e
->prefix
[EIGRP_FILTER_IN
];
908 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_IN
];
909 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_IN
];
911 /* Check if any list fits */
912 if ((alist
&& access_list_apply (alist
,
913 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
914 (plist
&& prefix_list_apply (plist
,
915 (struct prefix
*) dest_addr
) == PREFIX_DENY
)||
916 (alist_i
&& access_list_apply (alist_i
,
917 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
918 (plist_i
&& prefix_list_apply (plist_i
,
919 (struct prefix
*) dest_addr
) == PREFIX_DENY
))
921 /* do not send filtered route */
922 zlog_info("Filtered prefix %s will be removed.",
923 inet_ntoa(dest_addr
->prefix
));
925 tlv_max
= eigrp_IPv4_InternalTLV_new();
926 tlv_max
->type
= EIGRP_TLV_IPv4_INT
;
927 tlv_max
->length
= 28U;
928 tlv_max
->metric
= pe
->reported_metric
;
929 /* set delay to MAX */
930 tlv_max
->metric
.delay
= EIGRP_MAX_METRIC
;
931 tlv_max
->destination
= pe
->destination_ipv4
->prefix
;
932 tlv_max
->prefix_length
= pe
->destination_ipv4
->prefixlen
;
934 /* prepare message for FSM */
935 struct eigrp_fsm_action_message
*fsm_msg
;
936 fsm_msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
937 sizeof(struct eigrp_fsm_action_message
));
939 struct eigrp_neighbor_entry
*entry
=
940 eigrp_prefix_entry_lookup(pe
->entries
, nbr
);
942 fsm_msg
->packet_type
= EIGRP_OPC_UPDATE
;
944 fsm_msg
->data_type
= EIGRP_TLV_IPv4_INT
;
945 fsm_msg
->adv_router
= nbr
;
946 fsm_msg
->data
.ipv4_int_type
= tlv_max
;
947 fsm_msg
->entry
= entry
;
948 fsm_msg
->prefix
= pe
;
950 /* send message to FSM */
951 int event
= eigrp_get_fsm_event(fsm_msg
);
952 eigrp_fsm_event(fsm_msg
, event
);
954 /* free memory used by TLV */
955 eigrp_IPv4_InternalTLV_free (tlv_max
);
961 /* NULL the pointer */
964 /* delete processed prefix from list */
965 listnode_delete(prefixes
, pe
);
967 /* if there are enough prefixes, send packet */
968 if(send_prefixes
>= EIGRP_TLV_MAX_IPv4
)
972 /* compute Auth digest */
973 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) &&
974 (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
976 eigrp_make_md5_digest(nbr
->ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
980 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
983 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
985 /*This ack number we await from neighbor*/
986 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
988 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
989 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
990 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
992 /*Put packet to retransmission queue*/
993 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
995 if (nbr
->retrans_queue
->count
== 1)
997 eigrp_send_packet_reliably(nbr
);
1002 * @fn eigrp_update_send_GR_thread
1004 * @param[in] thread contains neighbor who would receive Graceful restart
1006 * @return int always 0
1009 * Function used for sending Graceful restart Update packet
1010 * in thread, it is prepared for multiple chunks of packet.
1012 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
1015 eigrp_update_send_GR_thread(struct thread
*thread
)
1017 struct eigrp_neighbor
*nbr
;
1019 /* get argument from thread */
1020 nbr
= THREAD_ARG(thread
);
1021 /* remove this thread pointer */
1022 nbr
->t_nbr_send_gr
= NULL
;
1024 /* if there is packet waiting in queue,
1025 * schedule this thread again with small delay */
1026 if(nbr
->retrans_queue
->count
> 0)
1028 nbr
->t_nbr_send_gr
= NULL
;
1029 thread_add_timer_msec(master
, eigrp_update_send_GR_thread
, nbr
, 10,
1030 &nbr
->t_nbr_send_gr
);
1034 /* send GR EIGRP packet chunk */
1035 eigrp_update_send_GR_part(nbr
);
1037 /* if it wasn't last chunk, schedule this thread again */
1038 if(nbr
->nbr_gr_packet_type
!= EIGRP_PACKET_PART_LAST
) {
1039 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
1040 nbr
->t_nbr_send_gr
= NULL
;
1047 * @fn eigrp_update_send_GR
1049 * @param[in] nbr Neighbor who would receive Graceful restart
1050 * @param[in] gr_type Who executed Graceful restart
1051 * @param[in] vty Virtual terminal for log output
1056 * Function used for sending Graceful restart Update packet:
1057 * Creates Update packet with INIT, RS, EOT flags and include
1058 * all route except those filtered
1061 eigrp_update_send_GR (struct eigrp_neighbor
*nbr
, enum GR_type gr_type
, struct vty
*vty
)
1063 struct eigrp_prefix_entry
*pe2
;
1064 struct listnode
*node2
, *nnode2
;
1065 struct list
*prefixes
;
1067 if(gr_type
== EIGRP_GR_FILTER
)
1069 /* function was called after applying filtration */
1070 zlog_info("Neighbor %s (%s) is resync: route configuration changed",
1071 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
1073 else if(gr_type
== EIGRP_GR_MANUAL
)
1075 /* Graceful restart was called manually */
1076 zlog_info("Neighbor %s (%s) is resync: manually cleared",
1077 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
1081 vty_time_print (vty
, 0);
1082 vty_out (vty
, "Neighbor %s (%s) is resync: manually cleared%s",
1083 inet_ntoa (nbr
->src
),
1084 ifindex2ifname (nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
),
1089 prefixes
= list_new();
1090 /* add all prefixes from topology table to list */
1091 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node2
, nnode2
, pe2
))
1093 listnode_add(prefixes
, pe2
);
1096 /* save prefixes to neighbor */
1097 nbr
->nbr_gr_prefixes_send
= prefixes
;
1098 /* indicate, that this is first GR Update packet chunk */
1099 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_FIRST
;
1100 /* execute packet sending in thread */
1101 thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
1102 nbr
->t_nbr_send_gr
= NULL
;
1106 * @fn eigrp_update_send_interface_GR
1108 * @param[in] ei Interface to neighbors of which the GR is sent
1109 * @param[in] gr_type Who executed Graceful restart
1110 * @param[in] vty Virtual terminal for log output
1115 * Function used for sending Graceful restart Update packet
1116 * to all neighbors on specified interface.
1119 eigrp_update_send_interface_GR (struct eigrp_interface
*ei
, enum GR_type gr_type
, struct vty
*vty
)
1121 struct listnode
*node
;
1122 struct eigrp_neighbor
*nbr
;
1124 /* iterate over all neighbors on eigrp interface */
1125 for (ALL_LIST_ELEMENTS_RO(ei
->nbrs
, node
, nbr
))
1127 /* send GR to neighbor */
1128 eigrp_update_send_GR(nbr
, gr_type
, vty
);
1133 * @fn eigrp_update_send_process_GR
1135 * @param[in] eigrp EIGRP process
1136 * @param[in] gr_type Who executed Graceful restart
1137 * @param[in] vty Virtual terminal for log output
1142 * Function used for sending Graceful restart Update packet
1143 * to all neighbors in eigrp process.
1146 eigrp_update_send_process_GR (struct eigrp
*eigrp
, enum GR_type gr_type
, struct vty
*vty
)
1148 struct listnode
*node
;
1149 struct eigrp_interface
*ei
;
1151 /* iterate over all eigrp interfaces */
1152 for (ALL_LIST_ELEMENTS_RO (eigrp
->eiflist
, node
, ei
))
1154 /* send GR to all neighbors on interface */
1155 eigrp_update_send_interface_GR(ei
, gr_type
, vty
);