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
28 * along with GNU Zebra; see the file COPYING. If not, write to the Free
29 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
41 #include "sockunion.h"
49 #include "plist_int.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"
68 * @fn remove_received_prefix_gr
70 * @param[in] nbr_prefixes List of neighbor prefixes
71 * @param[in] recv_prefix Prefix which needs to be removed from list
76 * Function is used for removing received prefix
77 * from list of neighbor prefixes
80 remove_received_prefix_gr (struct list
*nbr_prefixes
, struct eigrp_prefix_entry
*recv_prefix
)
82 struct listnode
*node1
, *node11
;
83 struct eigrp_prefix_entry
*prefix
;
85 /* iterate over all prefixes in list */
86 for (ALL_LIST_ELEMENTS(nbr_prefixes
, node1
, node11
, prefix
))
88 /* remove prefix from list if found */
89 if (prefix
== recv_prefix
)
91 listnode_delete(nbr_prefixes
, prefix
);
97 * @fn eigrp_update_receive_GR_ask
99 * @param[in] eigrp EIGRP process
100 * @param[in] nbr Neighbor update of who we received
101 * @param[in] nbr_prefixes Prefixes which weren't advertised
106 * Function is used for notifying FSM about prefixes which
107 * weren't advertised by neighbor:
108 * We will send message to FSM with prefix delay set to infinity.
111 eigrp_update_receive_GR_ask (struct eigrp
*eigrp
, struct eigrp_neighbor
*nbr
, 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
))
120 zlog_debug("GR receive: Neighbor not advertised %s/%d",
121 inet_ntoa(prefix
->destination_ipv4
->prefix
),
122 prefix
->destination_ipv4
->prefixlen
);
124 /* create internal IPv4 TLV with infinite delay */
125 tlv_max
= eigrp_IPv4_InternalTLV_new();
126 tlv_max
->type
= EIGRP_TLV_IPv4_INT
;
127 tlv_max
->length
= 28U;
128 tlv_max
->metric
= prefix
->reported_metric
;
129 /* set delay to MAX */
130 tlv_max
->metric
.delay
= EIGRP_MAX_METRIC
;
131 tlv_max
->destination
= prefix
->destination_ipv4
->prefix
;
132 tlv_max
->prefix_length
= prefix
->destination_ipv4
->prefixlen
;
135 /* prepare message for FSM */
136 struct eigrp_fsm_action_message
*fsm_msg
;
137 fsm_msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
138 sizeof(struct eigrp_fsm_action_message
));
140 struct eigrp_neighbor_entry
*entry
=
141 eigrp_prefix_entry_lookup(prefix
->entries
, nbr
);
143 fsm_msg
->packet_type
= EIGRP_OPC_UPDATE
;
144 fsm_msg
->eigrp
= eigrp
;
145 fsm_msg
->data_type
= EIGRP_TLV_IPv4_INT
;
146 fsm_msg
->adv_router
= nbr
;
147 fsm_msg
->data
.ipv4_int_type
= tlv_max
;
148 fsm_msg
->entry
= entry
;
149 fsm_msg
->prefix
= prefix
;
151 /* send message to FSM */
152 int event
= eigrp_get_fsm_event(fsm_msg
);
153 eigrp_fsm_event(fsm_msg
, event
);
155 /* free memory used by TLV */
156 eigrp_IPv4_InternalTLV_free (tlv_max
);
161 * EIGRP UPDATE read function
164 eigrp_update_receive (struct eigrp
*eigrp
, struct ip
*iph
, struct eigrp_header
*eigrph
,
165 struct stream
* s
, struct eigrp_interface
*ei
, int size
)
167 struct eigrp_neighbor
*nbr
;
168 struct TLV_IPv4_Internal_type
*tlv
;
169 struct eigrp_prefix_entry
*pe
;
170 struct eigrp_neighbor_entry
*ne
;
174 struct access_list
*alist
;
175 struct prefix_list
*plist
;
177 u_char graceful_restart
;
178 u_char graceful_restart_final
;
179 struct list
*nbr_prefixes
;
181 /* increment statistics. */
184 /* get neighbor struct */
185 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
187 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
190 flags
= ntohl(eigrph
->flags
);
192 if (flags
& EIGRP_CR_FLAG
)
198 graceful_restart
= 0;
199 graceful_restart_final
= 0;
200 if((nbr
->recv_sequence_number
) == (ntohl(eigrph
->sequence
)))
203 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
204 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
205 zlog_debug("Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]",
206 size
, ifindex2ifname(nbr
->ei
->ifp
->ifindex
),
208 nbr
->recv_sequence_number
, flags
);
211 if((flags
== (EIGRP_INIT_FLAG
+EIGRP_RS_FLAG
+EIGRP_EOT_FLAG
)) && (!same
))
213 /* Graceful restart Update received with all routes */
215 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
216 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
));
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;
223 else if((flags
== (EIGRP_INIT_FLAG
+EIGRP_RS_FLAG
)) && (!same
))
225 /* Graceful restart Update received, routes also in next packet */
227 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
228 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
));
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;
237 else if((flags
== (EIGRP_EOT_FLAG
)) && (!same
))
239 /* If there was INIT+RS Update packet before,
240 * consider this as GR EOT */
242 if(nbr
->nbr_gr_prefixes
!= NULL
)
244 /* this is final packet of GR */
245 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
246 nbr
->nbr_gr_prefixes
= NULL
;
248 graceful_restart
= 1;
249 graceful_restart_final
= 1;
253 else if((flags
== (0)) && (!same
))
255 /* If there was INIT+RS Update packet before,
256 * consider this as GR not final packet */
258 if(nbr
->nbr_gr_prefixes
!= NULL
)
260 /* this is GR not final route packet */
261 nbr_prefixes
= nbr
->nbr_gr_prefixes
;
263 graceful_restart
= 1;
264 graceful_restart_final
= 0;
268 else if((flags
& EIGRP_INIT_FLAG
) && (!same
))
269 { /* When in pending state, send INIT update only if it wasn't
270 already sent before (only if init_sequence is 0) */
271 if((nbr
->state
== EIGRP_NEIGHBOR_PENDING
) && (nbr
->init_sequence_number
== 0))
272 eigrp_update_send_init(nbr
);
274 if (nbr
->state
== EIGRP_NEIGHBOR_UP
)
276 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
277 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
,nbr
);
278 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
279 zlog_info("Neighbor %s (%s) is down: peer restarted",
280 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
));
281 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_PENDING
);
282 zlog_info("Neighbor %s (%s) is pending: new adjacency",
283 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
));
284 eigrp_update_send_init(nbr
);
288 /*If there is topology information*/
289 while (s
->endp
> s
->getp
)
291 type
= stream_getw(s
);
292 if (type
== EIGRP_TLV_IPv4_INT
)
294 stream_set_getp(s
, s
->getp
- sizeof(u_int16_t
));
296 tlv
= eigrp_read_ipv4_tlv(s
);
298 /*searching if destination exists */
299 struct prefix_ipv4
*dest_addr
;
300 dest_addr
= prefix_ipv4_new();
301 dest_addr
->prefix
= tlv
->destination
;
302 dest_addr
->prefixlen
= tlv
->prefix_length
;
303 struct eigrp_prefix_entry
*dest
= eigrp_topology_table_lookup_ipv4(
304 eigrp
->topology_table
, dest_addr
);
306 /*if exists it comes to DUAL*/
309 /* remove received prefix from neighbor prefix list if in GR */
311 remove_received_prefix_gr(nbr_prefixes
, dest
);
313 struct eigrp_fsm_action_message
*msg
;
314 msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
315 sizeof(struct eigrp_fsm_action_message
));
316 struct eigrp_neighbor_entry
*entry
=
317 eigrp_prefix_entry_lookup(dest
->entries
, nbr
);
319 msg
->packet_type
= EIGRP_OPC_UPDATE
;
321 msg
->data_type
= EIGRP_TLV_IPv4_INT
;
322 msg
->adv_router
= nbr
;
323 msg
->data
.ipv4_int_type
= tlv
;
326 int event
= eigrp_get_fsm_event(msg
);
327 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
= dest_addr
;
336 pe
->state
= EIGRP_FSM_STATE_PASSIVE
;
337 pe
->nt
= EIGRP_TOPOLOGY_TYPE_REMOTE
;
339 ne
= eigrp_neighbor_entry_new();
341 ne
->adv_router
= nbr
;
342 ne
->reported_metric
= tlv
->metric
;
343 ne
->reported_distance
=
344 eigrp_calculate_metrics(eigrp
,
351 * Check if there is any access-list on interface (IN direction)
352 * and set distance to max
354 alist
= ei
->list
[EIGRP_FILTER_IN
];
357 zlog_info ("ALIST PROC IN: %s", alist
->name
);
359 zlog_info("ALIST je prazdny");
362 /* Check if access-list fits */
363 if (alist
&& access_list_apply (alist
,
364 (struct prefix
*) dest_addr
) == FILTER_DENY
)
366 /* If yes, set reported metric to Max */
367 zlog_info("PROC IN: Nastavujem metriku na MAX");
368 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
369 zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr
->prefix
));
371 zlog_info("PROC IN: NENastavujem metriku ");
372 ne
->distance
= eigrp_calculate_total_metrics(eigrp
, ne
);
375 plist
= e
->prefix
[EIGRP_FILTER_IN
];
378 zlog_info ("PLIST PROC IN: %s", plist
->name
);
380 zlog_info("PLIST PROC IN je prazdny");
383 /* Check if prefix-list fits */
384 if (plist
&& prefix_list_apply (plist
,
385 (struct prefix
*) dest_addr
) == FILTER_DENY
)
387 /* If yes, set reported metric to Max */
388 zlog_info("PLIST PROC IN: Nastavujem metriku na MAX");
389 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
390 zlog_info("PLIST PROC IN Prefix: %s", inet_ntoa(dest_addr
->prefix
));
392 zlog_info("PLIST PROC IN: NENastavujem metriku ");
395 /*Get access-list from current interface */
396 zlog_info("Checking access_list on interface: %s",ei
->ifp
->name
);
397 alist
= ei
->list
[EIGRP_FILTER_IN
];
399 zlog_info ("ALIST INT IN: %s", alist
->name
);
401 zlog_info("ALIST INT IN je prazdny");
404 /* Check if access-list fits */
405 if (alist
&& access_list_apply (alist
, (struct prefix
*) dest_addr
) == FILTER_DENY
)
407 /* If yes, set reported metric to Max */
408 zlog_info("INT IN: Nastavujem metriku na MAX");
409 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
410 zlog_info("INT IN Prefix: %s", inet_ntoa(dest_addr
->prefix
));
412 zlog_info("INT IN: NENastavujem metriku ");
415 plist
= ei
->prefix
[EIGRP_FILTER_IN
];
418 zlog_info ("PLIST INT IN: %s", plist
->name
);
420 zlog_info("PLIST INT IN je prazdny");
423 /* Check if prefix-list fits */
424 if (plist
&& prefix_list_apply (plist
,
425 (struct prefix
*) dest_addr
) == FILTER_DENY
)
427 /* If yes, set reported metric to Max */
428 zlog_info("PLIST INT IN: Nastavujem metriku na MAX");
429 ne
->reported_metric
.delay
= EIGRP_MAX_METRIC
;
430 zlog_info("PLIST INT IN Prefix: %s", inet_ntoa(dest_addr
->prefix
));
432 zlog_info("PLIST INT IN: NENastavujem metriku ");
438 ne
->distance
= eigrp_calculate_total_metrics(eigrp
, ne
);
440 zlog_info("<DEBUG PROC IN Distance: %x", ne
->distance
);
441 zlog_info("<DEBUG PROC IN Delay: %x", ne
->total_metric
.delay
);
443 pe
->fdistance
= pe
->distance
= pe
->rdistance
=
446 ne
->flags
= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG
;
448 eigrp_prefix_entry_add(eigrp
->topology_table
, pe
);
449 eigrp_neighbor_entry_add(pe
, ne
);
450 pe
->distance
= pe
->fdistance
= pe
->rdistance
=
452 pe
->reported_metric
= ne
->total_metric
;
453 eigrp_topology_update_node_flags(pe
);
455 pe
->req_action
|= EIGRP_FSM_NEED_UPDATE
;
456 listnode_add(eigrp
->topology_changes_internalIPV4
, pe
);
458 eigrp_IPv4_InternalTLV_free (tlv
);
462 /* ask about prefixes not present in GR update,
463 * if this is final GR packet */
464 if(graceful_restart_final
)
466 eigrp_update_receive_GR_ask(eigrp
, nbr
, nbr_prefixes
);
470 * We don't need to send separate Ack for INIT Update. INIT will be acked in EOT Update.
472 if ((nbr
->state
== EIGRP_NEIGHBOR_UP
) && !(flags
== EIGRP_INIT_FLAG
))
474 eigrp_hello_send_ack(nbr
);
477 eigrp_query_send_all(eigrp
);
478 eigrp_update_send_all(eigrp
, ei
);
481 /*send EIGRP Update packet*/
483 eigrp_update_send_init (struct eigrp_neighbor
*nbr
)
485 struct eigrp_packet
*ep
;
486 u_int16_t length
= EIGRP_HEADER_LEN
;
488 ep
= eigrp_packet_new(nbr
->ei
->ifp
->mtu
);
490 /* Prepare EIGRP INIT UPDATE header */
491 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
492 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
493 nbr
->ei
->eigrp
->sequence_number
,
494 nbr
->recv_sequence_number
);
496 eigrp_packet_header_init(EIGRP_OPC_UPDATE
, nbr
->ei
, ep
->s
, EIGRP_INIT_FLAG
,
497 nbr
->ei
->eigrp
->sequence_number
,
498 nbr
->recv_sequence_number
);
500 // encode Authentication TLV, if needed
501 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) && (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
) == FILTER_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
) == FILTER_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
) && (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
611 eigrp_make_md5_digest(nbr
->ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
615 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
618 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
620 /*This ack number we await from neighbor*/
621 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
623 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
624 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
625 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
627 /*Put packet to retransmission queue*/
628 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
630 if (nbr
->retrans_queue
->count
== 1)
632 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
) && (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
663 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,ei
);
667 for (ALL_LIST_ELEMENTS(ei
->eigrp
->topology_changes_internalIPV4
, node
, nnode
, pe
))
669 if(pe
->req_action
& EIGRP_FSM_NEED_UPDATE
)
671 /* Get destination address from prefix */
672 dest_addr
= pe
->destination_ipv4
;
677 //TODO: Work in progress
678 /* get list from eigrp process */
680 /* Get access-lists and prefix-lists from process and interface */
681 alist
= e
->list
[EIGRP_FILTER_OUT
];
682 plist
= e
->prefix
[EIGRP_FILTER_OUT
];
683 alist_i
= ei
->list
[EIGRP_FILTER_OUT
];
684 plist_i
= ei
->prefix
[EIGRP_FILTER_OUT
];
686 /* Check if any list fits */
687 if ((alist
&& access_list_apply (alist
,
688 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
689 (plist
&& prefix_list_apply (plist
,
690 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
691 (alist_i
&& access_list_apply (alist_i
,
692 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
693 (plist_i
&& prefix_list_apply (plist_i
,
694 (struct prefix
*) dest_addr
) == FILTER_DENY
))
696 zlog_info("PROC OUT: Skipping");
697 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
698 zlog_info("PROC OUT Prefix: %s", inet_ntoa(dest_addr
->prefix
));
701 zlog_info("PROC OUT: NENastavujem metriku ");
702 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
709 /* NULL the pointer */
717 eigrp_packet_free(ep
);
721 if((IF_DEF_PARAMS (ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) && (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
723 eigrp_make_md5_digest(ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
727 eigrp_packet_checksum(ei
, ep
->s
, length
);
730 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
732 /*This ack number we await from neighbor*/
733 ep
->sequence_number
= ei
->eigrp
->sequence_number
;
735 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
736 zlog_debug("Enqueuing Update length[%u] Seq [%u]",
737 length
, ep
->sequence_number
);
739 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node
, nnode
, nbr
))
741 if (nbr
->state
== EIGRP_NEIGHBOR_UP
)
743 /*Put packet to retransmission queue*/
744 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
746 if (nbr
->retrans_queue
->count
== 1)
748 eigrp_send_packet_reliably(nbr
);
755 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
) && (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
867 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,nbr
->ei
);
870 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
];
886 /* Check if any list fits */
887 if ((alist
&& access_list_apply (alist
,
888 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
889 (plist
&& prefix_list_apply (plist
,
890 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
891 (alist_i
&& access_list_apply (alist_i
,
892 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
893 (plist_i
&& prefix_list_apply (plist_i
,
894 (struct prefix
*) dest_addr
) == FILTER_DENY
))
896 /* do not send filtered route */
897 zlog_info("Filtered prefix %s won't be sent out.",
898 inet_ntoa(dest_addr
->prefix
));
902 /* sending route which wasn't filtered */
903 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
909 alist
= e
->list
[EIGRP_FILTER_IN
];
910 plist
= e
->prefix
[EIGRP_FILTER_IN
];
911 alist_i
= nbr
->ei
->list
[EIGRP_FILTER_IN
];
912 plist_i
= nbr
->ei
->prefix
[EIGRP_FILTER_IN
];
915 /* Check if any list fits */
916 if ((alist
&& access_list_apply (alist
,
917 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
918 (plist
&& prefix_list_apply (plist
,
919 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
920 (alist_i
&& access_list_apply (alist_i
,
921 (struct prefix
*) dest_addr
) == FILTER_DENY
)||
922 (plist_i
&& prefix_list_apply (plist_i
,
923 (struct prefix
*) dest_addr
) == FILTER_DENY
))
925 /* do not send filtered route */
926 zlog_info("Filtered prefix %s will be removed.",
927 inet_ntoa(dest_addr
->prefix
));
929 tlv_max
= eigrp_IPv4_InternalTLV_new();
930 tlv_max
->type
= EIGRP_TLV_IPv4_INT
;
931 tlv_max
->length
= 28U;
932 tlv_max
->metric
= pe
->reported_metric
;
933 /* set delay to MAX */
934 tlv_max
->metric
.delay
= EIGRP_MAX_METRIC
;
935 tlv_max
->destination
= pe
->destination_ipv4
->prefix
;
936 tlv_max
->prefix_length
= pe
->destination_ipv4
->prefixlen
;
939 /* prepare message for FSM */
940 struct eigrp_fsm_action_message
*fsm_msg
;
941 fsm_msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
942 sizeof(struct eigrp_fsm_action_message
));
944 struct eigrp_neighbor_entry
*entry
=
945 eigrp_prefix_entry_lookup(pe
->entries
, nbr
);
947 fsm_msg
->packet_type
= EIGRP_OPC_UPDATE
;
949 fsm_msg
->data_type
= EIGRP_TLV_IPv4_INT
;
950 fsm_msg
->adv_router
= nbr
;
951 fsm_msg
->data
.ipv4_int_type
= tlv_max
;
952 fsm_msg
->entry
= entry
;
953 fsm_msg
->prefix
= pe
;
955 /* send message to FSM */
956 int event
= eigrp_get_fsm_event(fsm_msg
);
957 eigrp_fsm_event(fsm_msg
, event
);
959 /* free memory used by TLV */
960 eigrp_IPv4_InternalTLV_free (tlv_max
);
966 /* NULL the pointer */
969 /* delete processed prefix from list */
970 listnode_delete(prefixes
, pe
);
972 /* if there are enough prefixes, send packet */
973 if(send_prefixes
>= EIGRP_TLV_MAX_IPv4
)
977 /* compute Auth digest */
978 if((IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) && (IF_DEF_PARAMS (nbr
->ei
->ifp
)->auth_keychain
!= NULL
))
980 eigrp_make_md5_digest(nbr
->ei
,ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
984 eigrp_packet_checksum(nbr
->ei
, ep
->s
, length
);
987 ep
->dst
.s_addr
= nbr
->src
.s_addr
;
989 /*This ack number we await from neighbor*/
990 ep
->sequence_number
= nbr
->ei
->eigrp
->sequence_number
;
992 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
993 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
994 ep
->length
, ep
->sequence_number
, inet_ntoa(ep
->dst
));
997 /*Put packet to retransmission queue*/
998 eigrp_fifo_push_head(nbr
->retrans_queue
, ep
);
1000 if (nbr
->retrans_queue
->count
== 1)
1002 eigrp_send_packet_reliably(nbr
);
1007 * @fn eigrp_update_send_GR_thread
1009 * @param[in] thread contains neighbor who would receive Graceful restart
1011 * @return int always 0
1014 * Function used for sending Graceful restart Update packet
1015 * in thread, it is prepared for multiple chunks of packet.
1017 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
1020 eigrp_update_send_GR_thread(struct thread
*thread
)
1022 struct eigrp_neighbor
*nbr
;
1024 /* get argument from thread */
1025 nbr
= THREAD_ARG(thread
);
1026 /* remove this thread pointer */
1027 nbr
->t_nbr_send_gr
= NULL
;
1029 /* if there is packet waiting in queue,
1030 * schedule this thread again with small delay */
1031 if(nbr
->retrans_queue
->count
> 0)
1033 nbr
->t_nbr_send_gr
= thread_add_timer_msec(master
, eigrp_update_send_GR_thread
, nbr
, 10);
1037 /* send GR EIGRP packet chunk */
1038 eigrp_update_send_GR_part(nbr
);
1040 /* if it wasn't last chunk, schedule this thread again */
1041 if(nbr
->nbr_gr_packet_type
!= EIGRP_PACKET_PART_LAST
)
1042 nbr
->t_nbr_send_gr
= thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
1048 * @fn eigrp_update_send_GR
1050 * @param[in] nbr Neighbor who would receive Graceful restart
1051 * @param[in] gr_type Who executed Graceful restart
1052 * @param[in] vty Virtual terminal for log output
1057 * Function used for sending Graceful restart Update packet:
1058 * Creates Update packet with INIT, RS, EOT flags and include
1059 * all route except those filtered
1062 eigrp_update_send_GR (struct eigrp_neighbor
*nbr
, enum GR_type gr_type
, struct vty
*vty
)
1064 struct eigrp_prefix_entry
*pe2
;
1065 struct listnode
*node2
, *nnode2
;
1066 struct list
*prefixes
;
1068 if(gr_type
== EIGRP_GR_FILTER
)
1070 /* function was called after applying filtration */
1071 zlog_info("Neighbor %s (%s) is resync: route configuration changed",
1072 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
));
1074 else if(gr_type
== EIGRP_GR_MANUAL
)
1076 /* Graceful restart was called manually */
1077 zlog_info("Neighbor %s (%s) is resync: manually cleared",
1078 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
));
1082 vty_time_print (vty
, 0);
1083 vty_out (vty
, "Neighbor %s (%s) is resync: manually cleared%s",
1084 inet_ntoa (nbr
->src
),
1085 ifindex2ifname (nbr
->ei
->ifp
->ifindex
),
1090 prefixes
= list_new();
1091 /* add all prefixes from topology table to list */
1092 for (ALL_LIST_ELEMENTS(nbr
->ei
->eigrp
->topology_table
, node2
, nnode2
, pe2
))
1094 listnode_add(prefixes
, pe2
);
1097 /* save prefixes to neighbor */
1098 nbr
->nbr_gr_prefixes_send
= prefixes
;
1099 /* indicate, that this is first GR Update packet chunk */
1100 nbr
->nbr_gr_packet_type
= EIGRP_PACKET_PART_FIRST
;
1101 /* execute packet sending in thread */
1102 nbr
->t_nbr_send_gr
= thread_execute(master
, eigrp_update_send_GR_thread
, nbr
, 0);
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
);