]> git.proxmox.com Git - mirror_frr.git/blame - eigrpd/eigrp_update.c
redhat: Add option to build with RPKI
[mirror_frr.git] / eigrpd / eigrp_update.c
CommitLineData
7f57883e
DS
1/*
2 * EIGRP Sending and Receiving EIGRP Update Packets.
3 * Copyright (C) 2013-2016
4 * Authors:
5 * Donnie Savage
6 * Jan Janovic
7 * Matej Perina
8 * Peter Orsag
9 * Peter Paluch
10 * Frantisek Gazo
11 * Tomas Hvorkovy
12 * Martin Kontsek
13 * Lukas Koribsky
14 *
15 * This file is part of GNU Zebra.
16 *
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
20 * later version.
21 *
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.
26 *
896014f4
DL
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
7f57883e
DS
30 */
31
32#include <zebra.h>
33
34#include "thread.h"
35#include "memory.h"
36#include "linklist.h"
37#include "prefix.h"
38#include "if.h"
39#include "table.h"
40#include "sockunion.h"
41#include "stream.h"
42#include "log.h"
43#include "sockopt.h"
44#include "checksum.h"
45#include "md5.h"
46#include "vty.h"
47#include "plist.h"
48#include "plist_int.h"
49#include "routemap.h"
50#include "vty.h"
51
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"
65
71b52ef2
DS
66bool eigrp_update_prefix_apply(struct eigrp *eigrp,
67 struct eigrp_interface *ei,
68 int in, struct prefix *prefix)
69{
70 struct access_list *alist;
71 struct prefix_list *plist;
72
73 alist = eigrp->list[in];
74 if (alist && access_list_apply(alist, prefix) == FILTER_DENY)
75 return true;
76
77 plist = eigrp->prefix[in];
78 if (plist && prefix_list_apply(plist, prefix) == PREFIX_DENY)
79 return true;
80
81 alist = ei->list[in];
82 if (alist && access_list_apply(alist, prefix) == FILTER_DENY)
83 return true;
84
85 plist = ei->prefix[in];
86 if (plist && prefix_list_apply(plist, prefix) == PREFIX_DENY)
87 return true;
88
89 return false;
90}
91
7f57883e
DS
92/**
93 * @fn remove_received_prefix_gr
94 *
95 * @param[in] nbr_prefixes List of neighbor prefixes
d62a17ae 96 * @param[in] recv_prefix Prefix which needs to be removed from
97 * list
7f57883e
DS
98 *
99 * @return void
100 *
101 * @par
102 * Function is used for removing received prefix
103 * from list of neighbor prefixes
104 */
d62a17ae 105static void remove_received_prefix_gr(struct list *nbr_prefixes,
106 struct eigrp_prefix_entry *recv_prefix)
7f57883e 107{
d62a17ae 108 struct listnode *node1, *node11;
109 struct eigrp_prefix_entry *prefix = NULL;
110
111 /* iterate over all prefixes in list */
112 for (ALL_LIST_ELEMENTS(nbr_prefixes, node1, node11, prefix)) {
113 /* remove prefix from list if found */
114 if (prefix == recv_prefix) {
115 listnode_delete(nbr_prefixes, prefix);
116 }
117 }
7f57883e
DS
118}
119
120/**
121 * @fn eigrp_update_receive_GR_ask
122 *
123 * @param[in] eigrp EIGRP process
d62a17ae 124 * @param[in] nbr Neighbor update of who we
125 * received
7f57883e
DS
126 * @param[in] nbr_prefixes Prefixes which weren't advertised
127 *
128 * @return void
129 *
130 * @par
131 * Function is used for notifying FSM about prefixes which
132 * weren't advertised by neighbor:
133 * We will send message to FSM with prefix delay set to infinity.
134 */
d62a17ae 135static void eigrp_update_receive_GR_ask(struct eigrp *eigrp,
136 struct eigrp_neighbor *nbr,
137 struct list *nbr_prefixes)
7f57883e 138{
d62a17ae 139 struct listnode *node1;
140 struct eigrp_prefix_entry *prefix;
5ca6df78 141 struct eigrp_fsm_action_message fsm_msg;
d62a17ae 142
143 /* iterate over all prefixes which weren't advertised by neighbor */
144 for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) {
02b45998
DS
145 char buffer[PREFIX_STRLEN];
146 zlog_debug("GR receive: Neighbor not advertised %s",
147 prefix2str(prefix->destination,
148 buffer, PREFIX_STRLEN));
d62a17ae 149
5ca6df78 150 fsm_msg.metrics = prefix->reported_metric;
d62a17ae 151 /* set delay to MAX */
5ca6df78 152 fsm_msg.metrics.delay = EIGRP_MAX_METRIC;
d62a17ae 153
255ab940 154 struct eigrp_nexthop_entry *entry =
d62a17ae 155 eigrp_prefix_entry_lookup(prefix->entries, nbr);
156
92035b1d
DS
157 fsm_msg.packet_type = EIGRP_OPC_UPDATE;
158 fsm_msg.eigrp = eigrp;
7cfa4322 159 fsm_msg.data_type = EIGRP_INT;
92035b1d 160 fsm_msg.adv_router = nbr;
92035b1d
DS
161 fsm_msg.entry = entry;
162 fsm_msg.prefix = prefix;
d62a17ae 163
164 /* send message to FSM */
6118272f 165 eigrp_fsm_event(&fsm_msg);
d62a17ae 166 }
7f57883e
DS
167}
168
169/*
170 * EIGRP UPDATE read function
171 */
d62a17ae 172void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
173 struct eigrp_header *eigrph, struct stream *s,
174 struct eigrp_interface *ei, int size)
7f57883e 175{
d62a17ae 176 struct eigrp_neighbor *nbr;
177 struct TLV_IPv4_Internal_type *tlv;
178 struct eigrp_prefix_entry *pe;
255ab940 179 struct eigrp_nexthop_entry *ne;
d62a17ae 180 u_int32_t flags;
181 u_int16_t type;
c283f389 182 u_int16_t length;
d62a17ae 183 u_char same;
476a1469 184 struct prefix dest_addr;
d62a17ae 185 u_char graceful_restart;
186 u_char graceful_restart_final;
187 struct list *nbr_prefixes = NULL;
188
189 /* increment statistics. */
190 ei->update_in++;
191
192 /* get neighbor struct */
193 nbr = eigrp_nbr_get(ei, eigrph, iph);
194
195 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
196 assert(nbr);
197
198 flags = ntohl(eigrph->flags);
199
200 if (flags & EIGRP_CR_FLAG) {
201 return;
202 }
203
204 same = 0;
205 graceful_restart = 0;
206 graceful_restart_final = 0;
207 if ((nbr->recv_sequence_number) == (ntohl(eigrph->sequence)))
208 same = 1;
209
210 nbr->recv_sequence_number = ntohl(eigrph->sequence);
211 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
212 zlog_debug(
213 "Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]",
214 size,
215 ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT),
216 inet_ntoa(nbr->src), nbr->recv_sequence_number, flags);
217
218
219 if ((flags == (EIGRP_INIT_FLAG + EIGRP_RS_FLAG + EIGRP_EOT_FLAG))
220 && (!same)) {
221 /* Graceful restart Update received with all routes */
222
223 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
224 inet_ntoa(nbr->src),
225 ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
226
227 /* get all prefixes from neighbor from topology table */
228 nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr);
229 graceful_restart = 1;
230 graceful_restart_final = 1;
231 } else if ((flags == (EIGRP_INIT_FLAG + EIGRP_RS_FLAG)) && (!same)) {
232 /* Graceful restart Update received, routes also in next packet
233 */
234
235 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
236 inet_ntoa(nbr->src),
237 ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
238
239 /* get all prefixes from neighbor from topology table */
240 nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr);
241 /* save prefixes to neighbor for later use */
242 nbr->nbr_gr_prefixes = nbr_prefixes;
243 graceful_restart = 1;
244 graceful_restart_final = 0;
245 } else if ((flags == (EIGRP_EOT_FLAG)) && (!same)) {
246 /* If there was INIT+RS Update packet before,
247 * consider this as GR EOT */
248
249 if (nbr->nbr_gr_prefixes != NULL) {
250 /* this is final packet of GR */
251 nbr_prefixes = nbr->nbr_gr_prefixes;
252 nbr->nbr_gr_prefixes = NULL;
253
254 graceful_restart = 1;
255 graceful_restart_final = 1;
256 }
257
258 } else if ((flags == (0)) && (!same)) {
259 /* If there was INIT+RS Update packet before,
260 * consider this as GR not final packet */
261
262 if (nbr->nbr_gr_prefixes != NULL) {
263 /* this is GR not final route packet */
264 nbr_prefixes = nbr->nbr_gr_prefixes;
265
266 graceful_restart = 1;
267 graceful_restart_final = 0;
268 }
269
270 } else if ((flags & EIGRP_INIT_FLAG)
271 && (!same)) { /* When in pending state, send INIT update only
272 if it wasn't
273 already sent before (only if init_sequence
274 is 0) */
275 if ((nbr->state == EIGRP_NEIGHBOR_PENDING)
276 && (nbr->init_sequence_number == 0))
277 eigrp_update_send_init(nbr);
278
279 if (nbr->state == EIGRP_NEIGHBOR_UP) {
280 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
281 eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr);
282 nbr->recv_sequence_number = ntohl(eigrph->sequence);
283 zlog_info("Neighbor %s (%s) is down: peer restarted",
284 inet_ntoa(nbr->src),
285 ifindex2ifname(nbr->ei->ifp->ifindex,
286 VRF_DEFAULT));
287 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING);
288 zlog_info("Neighbor %s (%s) is pending: new adjacency",
289 inet_ntoa(nbr->src),
290 ifindex2ifname(nbr->ei->ifp->ifindex,
291 VRF_DEFAULT));
292 eigrp_update_send_init(nbr);
293 }
294 }
295
296 /*If there is topology information*/
297 while (s->endp > s->getp) {
298 type = stream_getw(s);
c283f389
DS
299 switch (type) {
300 case EIGRP_TLV_IPv4_INT:
d62a17ae 301 stream_set_getp(s, s->getp - sizeof(u_int16_t));
302
303 tlv = eigrp_read_ipv4_tlv(s);
304
305 /*searching if destination exists */
306 dest_addr.family = AF_INET;
476a1469 307 dest_addr.u.prefix4 = tlv->destination;
d62a17ae 308 dest_addr.prefixlen = tlv->prefix_length;
309 struct eigrp_prefix_entry *dest =
310 eigrp_topology_table_lookup_ipv4(
311 eigrp->topology_table, &dest_addr);
312
313 /*if exists it comes to DUAL*/
314 if (dest != NULL) {
315 /* remove received prefix from neighbor prefix
316 * list if in GR */
317 if (graceful_restart)
318 remove_received_prefix_gr(nbr_prefixes,
319 dest);
320
92035b1d 321 struct eigrp_fsm_action_message msg;
255ab940 322 struct eigrp_nexthop_entry *entry =
d62a17ae 323 eigrp_prefix_entry_lookup(dest->entries,
324 nbr);
325
92035b1d
DS
326 msg.packet_type = EIGRP_OPC_UPDATE;
327 msg.eigrp = eigrp;
7cfa4322 328 msg.data_type = EIGRP_INT;
92035b1d 329 msg.adv_router = nbr;
db6ec9ff 330 msg.metrics = tlv->metric;
92035b1d
DS
331 msg.entry = entry;
332 msg.prefix = dest;
6118272f 333 eigrp_fsm_event(&msg);
d62a17ae 334 } else {
335 /*Here comes topology information save*/
336 pe = eigrp_prefix_entry_new();
337 pe->serno = eigrp->serno;
02b45998
DS
338 pe->destination = (struct prefix *)prefix_ipv4_new();
339 prefix_copy(pe->destination,
476a1469 340 &dest_addr);
d62a17ae 341 pe->af = AF_INET;
342 pe->state = EIGRP_FSM_STATE_PASSIVE;
343 pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE;
344
255ab940 345 ne = eigrp_nexthop_entry_new();
d62a17ae 346 ne->ei = ei;
347 ne->adv_router = nbr;
348 ne->reported_metric = tlv->metric;
349 ne->reported_distance = eigrp_calculate_metrics(
350 eigrp, tlv->metric);
351 /*
352 * Filtering
353 */
71b52ef2
DS
354 if (eigrp_update_prefix_apply(eigrp, ei,
355 EIGRP_FILTER_IN,
356 &dest_addr))
357 ne->reported_metric.delay = EIGRP_MAX_METRIC;
d62a17ae 358
359 ne->distance = eigrp_calculate_total_metrics(
360 eigrp, ne);
361
362 pe->fdistance = pe->distance = pe->rdistance =
363 ne->distance;
364 ne->prefix = pe;
255ab940 365 ne->flags = EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG;
d62a17ae 366
367 eigrp_prefix_entry_add(eigrp->topology_table,
368 pe);
255ab940 369 eigrp_nexthop_entry_add(pe, ne);
d62a17ae 370 pe->distance = pe->fdistance = pe->rdistance =
371 ne->distance;
372 pe->reported_metric = ne->total_metric;
373 eigrp_topology_update_node_flags(pe);
374
375 pe->req_action |= EIGRP_FSM_NEED_UPDATE;
376 listnode_add(
377 eigrp->topology_changes_internalIPV4,
378 pe);
379 }
380 eigrp_IPv4_InternalTLV_free(tlv);
c283f389
DS
381 break;
382
383 case EIGRP_TLV_IPv4_EXT:
384 /* DVS: processing of external routes needs packet and fsm work.
385 * for now, lets just not creash the box
386 */
387 default:
388 length = stream_getw(s);
389 // -2 for type, -2 for len
390 for (length-=4; length ; length--) {
391 (void)stream_getc(s);
392 }
d62a17ae 393 }
394 }
395
396 /* ask about prefixes not present in GR update,
397 * if this is final GR packet */
398 if (graceful_restart_final) {
399 eigrp_update_receive_GR_ask(eigrp, nbr, nbr_prefixes);
400 }
401
402 /*
403 * We don't need to send separate Ack for INIT Update. INIT will be
404 * acked in EOT Update.
405 */
406 if ((nbr->state == EIGRP_NEIGHBOR_UP) && !(flags == EIGRP_INIT_FLAG)) {
407 eigrp_hello_send_ack(nbr);
408 }
409
410 eigrp_query_send_all(eigrp);
411 eigrp_update_send_all(eigrp, ei);
dbfd865b
DS
412
413 if (nbr_prefixes)
affe9e99 414 list_delete_and_null(&nbr_prefixes);
7f57883e
DS
415}
416
417/*send EIGRP Update packet*/
d62a17ae 418void eigrp_update_send_init(struct eigrp_neighbor *nbr)
7f57883e 419{
d62a17ae 420 struct eigrp_packet *ep;
421 u_int16_t length = EIGRP_HEADER_LEN;
422
907b4303 423 ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
d62a17ae 424
425 /* Prepare EIGRP INIT UPDATE header */
426 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
427 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
428 nbr->ei->eigrp->sequence_number,
429 nbr->recv_sequence_number);
430
cf2f4dae
DS
431 eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp,
432 ep->s, EIGRP_INIT_FLAG,
433 nbr->ei->eigrp->sequence_number,
434 nbr->recv_sequence_number);
d62a17ae 435
436 // encode Authentication TLV, if needed
b748db67
DS
437 if ((nbr->ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
438 && (nbr->ei->params.auth_keychain != NULL)) {
d62a17ae 439 length += eigrp_add_authTLV_MD5_to_stream(ep->s, nbr->ei);
440 eigrp_make_md5_digest(nbr->ei, ep->s,
441 EIGRP_AUTH_UPDATE_INIT_FLAG);
442 }
443
444 /* EIGRP Checksum */
445 eigrp_packet_checksum(nbr->ei, ep->s, length);
446
447 ep->length = length;
448 ep->dst.s_addr = nbr->src.s_addr;
449
450 /*This ack number we await from neighbor*/
451 nbr->init_sequence_number = nbr->ei->eigrp->sequence_number;
452 ep->sequence_number = nbr->ei->eigrp->sequence_number;
453 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
454 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
455 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
456
457 /*Put packet to retransmission queue*/
f90f65a2 458 eigrp_fifo_push(nbr->retrans_queue, ep);
d62a17ae 459
460 if (nbr->retrans_queue->count == 1) {
461 eigrp_send_packet_reliably(nbr);
462 }
7f57883e
DS
463}
464
7ecf0a4d
DS
465static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor *nbr,
466 struct eigrp_packet *ep,
467 u_int32_t seq_no,
468 int length)
469{
b748db67
DS
470 if((nbr->ei->params.auth_type == EIGRP_AUTH_TYPE_MD5) &&
471 (nbr->ei->params.auth_keychain != NULL)) {
7ecf0a4d
DS
472 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
473 }
474
475 /* EIGRP Checksum */
476 eigrp_packet_checksum(nbr->ei, ep->s, length);
477
478 ep->length = length;
479 ep->dst.s_addr = nbr->src.s_addr;
480
481 /*This ack number we await from neighbor*/
482 ep->sequence_number = seq_no;
483
484 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
485 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
486 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
487
488 /*Put packet to retransmission queue*/
f90f65a2 489 eigrp_fifo_push(nbr->retrans_queue, ep);
17a2f658
DS
490
491 if (nbr->retrans_queue->count == 1)
492 eigrp_send_packet_reliably(nbr);
7ecf0a4d
DS
493}
494
a6e8810e
DS
495static void eigrp_update_send_to_all_nbrs(struct eigrp_interface *ei,
496 struct eigrp_packet *ep)
497{
498 struct listnode *node, *nnode;
499 struct eigrp_neighbor *nbr;
500 bool packet_sent = false;
501
502 for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
503 struct eigrp_packet *ep_dup;
504
505 if (nbr->state != EIGRP_NEIGHBOR_UP)
506 continue;
507
508 if (packet_sent)
509 ep_dup = eigrp_packet_duplicate(ep, NULL);
510 else
511 ep_dup = ep;
512
513 ep_dup->nbr = nbr;
514 packet_sent = true;
515 /*Put packet to retransmission queue*/
516 eigrp_fifo_push(nbr->retrans_queue, ep_dup);
517
518 if (nbr->retrans_queue->count == 1) {
519 eigrp_send_packet_reliably(nbr);
520 }
521 }
522
523 if (!packet_sent)
524 eigrp_packet_free(ep);
525}
526
d62a17ae 527void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
7f57883e 528{
d62a17ae 529 struct eigrp_packet *ep;
d62a17ae 530 u_int16_t length = EIGRP_HEADER_LEN;
255ab940 531 struct eigrp_nexthop_entry *te;
d62a17ae 532 struct eigrp_prefix_entry *pe;
9ca66cc7 533 struct listnode *node2, *nnode2;
3a45a729
DS
534 struct eigrp_interface *ei = nbr->ei;
535 struct eigrp *eigrp = ei->eigrp;
02b45998 536 struct prefix *dest_addr;
3a45a729 537 u_int32_t seq_no = eigrp->sequence_number;
9ca66cc7
DS
538 u_int16_t mtu = ei->ifp->mtu;
539 struct route_node *rn;
d62a17ae 540
9ca66cc7 541 ep = eigrp_packet_new(mtu, nbr);
d62a17ae 542
543 /* Prepare EIGRP EOT UPDATE header */
3a45a729 544 eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp,
cf2f4dae
DS
545 ep->s, EIGRP_EOT_FLAG,
546 seq_no, nbr->recv_sequence_number);
d62a17ae 547
548 // encode Authentication TLV, if needed
b748db67
DS
549 if((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5) &&
550 (ei->params.auth_keychain != NULL)) {
3a45a729 551 length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
d62a17ae 552 }
553
9ca66cc7
DS
554 for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
555 if (!rn->info)
556 continue;
557
558 pe = rn->info;
d62a17ae 559 for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) {
3a45a729 560 if (eigrp_nbr_split_horizon_check(te, ei))
d62a17ae 561 continue;
562
03161b73 563 if ((length + EIGRP_TLV_MAX_IPV4_BYTE) > mtu) {
7ecf0a4d 564 eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
7ecf0a4d
DS
565 seq_no++;
566
567 length = EIGRP_HEADER_LEN;
9ca66cc7
DS
568 ep = eigrp_packet_new(mtu, nbr);
569 eigrp_packet_header_init(EIGRP_OPC_UPDATE,
570 nbr->ei->eigrp,
cf2f4dae 571 ep->s, EIGRP_EOT_FLAG,
9ca66cc7
DS
572 seq_no,
573 nbr->recv_sequence_number);
7ecf0a4d 574
b748db67
DS
575 if((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5) &&
576 (ei->params.auth_keychain != NULL))
7ecf0a4d 577 {
3a45a729 578 length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
7ecf0a4d
DS
579 }
580 }
d62a17ae 581 /* Get destination address from prefix */
02b45998 582 dest_addr = pe->destination;
d62a17ae 583
d62a17ae 584 /* Check if any list fits */
71b52ef2
DS
585 if (eigrp_update_prefix_apply(eigrp, ei,
586 EIGRP_FILTER_OUT,
587 dest_addr))
d62a17ae 588 continue;
71b52ef2 589 else {
7ecf0a4d 590 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
d62a17ae 591 }
d62a17ae 592 }
593 }
594
7ecf0a4d 595 eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
3a45a729 596 eigrp->sequence_number = seq_no++;
7f57883e
DS
597}
598
d62a17ae 599void eigrp_update_send(struct eigrp_interface *ei)
7f57883e 600{
d62a17ae 601 struct eigrp_packet *ep;
602 struct listnode *node, *nnode;
d62a17ae 603 struct eigrp_prefix_entry *pe;
604 u_char has_tlv;
3a45a729 605 struct eigrp *eigrp = ei->eigrp;
02b45998 606 struct prefix *dest_addr;
3a45a729 607 u_int32_t seq_no = eigrp->sequence_number;
a6e8810e
DS
608
609 if (ei->nbrs->count == 0)
610 return;
d62a17ae 611
612 u_int16_t length = EIGRP_HEADER_LEN;
613
907b4303 614 ep = eigrp_packet_new(ei->ifp->mtu, NULL);
d62a17ae 615
616 /* Prepare EIGRP INIT UPDATE header */
3a45a729 617 eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp,
cf2f4dae 618 ep->s, 0, seq_no, 0);
d62a17ae 619
620 // encode Authentication TLV, if needed
b748db67
DS
621 if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
622 && (ei->params.auth_keychain != NULL)) {
d62a17ae 623 length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei);
624 }
625
626 has_tlv = 0;
627 for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node,
628 nnode, pe)) {
255ab940 629 struct eigrp_nexthop_entry *ne;
d62a17ae 630
a75c1cc1
DS
631 if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE))
632 continue;
d62a17ae 633
cd044247
DS
634 ne = listnode_head(pe->entries);
635 if (eigrp_nbr_split_horizon_check(ne, ei))
636 continue;
637
03161b73
DS
638 if ((length + EIGRP_TLV_MAX_IPV4_BYTE) >
639 (u_int16_t)ei->ifp->mtu) {
b748db67
DS
640 if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
641 && (ei->params.auth_keychain != NULL)) {
a6e8810e
DS
642 eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);
643 }
644
645 eigrp_packet_checksum(ei, ep->s, length);
646 ep->length = length;
647
648 ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
649
650 ep->sequence_number = seq_no;
651 seq_no++;
652 eigrp_update_send_to_all_nbrs(ei, ep);
653
654 length = EIGRP_HEADER_LEN;
655 ep = eigrp_packet_new(ei->ifp->mtu, NULL);
3a45a729 656 eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp,
cf2f4dae 657 ep->s, 0, seq_no, 0);
b748db67
DS
658 if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
659 && (ei->params.auth_keychain != NULL)) {
a6e8810e
DS
660 length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei);
661 }
662 has_tlv = 0;
663 }
a75c1cc1 664 /* Get destination address from prefix */
02b45998 665 dest_addr = pe->destination;
d62a17ae 666
71b52ef2
DS
667 if (eigrp_update_prefix_apply(eigrp, ei,
668 EIGRP_FILTER_OUT,
669 dest_addr)) {
a75c1cc1
DS
670 // pe->reported_metric.delay = EIGRP_MAX_METRIC;
671 continue;
672 } else {
673 length += eigrp_add_internalTLV_to_stream(ep->s,
674 pe);
675 has_tlv = 1;
d62a17ae 676 }
677 }
678
679 if (!has_tlv) {
680 eigrp_packet_free(ep);
681 return;
682 }
683
b748db67
DS
684 if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
685 && (ei->params.auth_keychain != NULL)) {
d62a17ae 686 eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);
687 }
688
689 /* EIGRP Checksum */
690 eigrp_packet_checksum(ei, ep->s, length);
691 ep->length = length;
692
693 ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
694
695 /*This ack number we await from neighbor*/
3a45a729 696 ep->sequence_number = eigrp->sequence_number;
d62a17ae 697
698 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
699 zlog_debug("Enqueuing Update length[%u] Seq [%u]", length,
700 ep->sequence_number);
701
a6e8810e
DS
702 eigrp_update_send_to_all_nbrs(ei, ep);
703 ei->eigrp->sequence_number = seq_no++;
7f57883e
DS
704}
705
d62a17ae 706void eigrp_update_send_all(struct eigrp *eigrp,
707 struct eigrp_interface *exception)
7f57883e 708{
d62a17ae 709 struct eigrp_interface *iface;
710 struct listnode *node, *node2, *nnode2;
711 struct eigrp_prefix_entry *pe;
712
713 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) {
714 if (iface != exception) {
715 eigrp_update_send(iface);
716 }
717 }
718
719 for (ALL_LIST_ELEMENTS(eigrp->topology_changes_internalIPV4, node2,
720 nnode2, pe)) {
721 if (pe->req_action & EIGRP_FSM_NEED_UPDATE) {
722 pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
723 listnode_delete(eigrp->topology_changes_internalIPV4,
724 pe);
d62a17ae 725 }
726 }
7f57883e
DS
727}
728
729/**
730 * @fn eigrp_update_send_GR_part
731 *
9d303b37
DL
732 * @param[in] nbr contains neighbor who would receive Graceful
733 * restart
7f57883e
DS
734 *
735 * @return void
736 *
737 * @par
738 * Function used for sending Graceful restart Update packet
739 * and if there are multiple chunks, send only one of them.
740 * It is called from thread. Do not call it directly.
741 *
742 * Uses nbr_gr_packet_type from neighbor.
743 */
d62a17ae 744static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
7f57883e 745{
d62a17ae 746 struct eigrp_packet *ep;
747 u_int16_t length = EIGRP_HEADER_LEN;
d62a17ae 748 struct eigrp_prefix_entry *pe;
02b45998 749 struct prefix *dest_addr;
3a45a729
DS
750 struct eigrp_interface *ei = nbr->ei;
751 struct eigrp *eigrp = ei->eigrp;
d62a17ae 752 struct list *prefixes;
753 u_int32_t flags;
754 unsigned int send_prefixes;
9ca66cc7 755 struct route_node *rn;
d62a17ae 756
757 /* get prefixes to send to neighbor */
758 prefixes = nbr->nbr_gr_prefixes_send;
759
760 send_prefixes = 0;
761 length = EIGRP_HEADER_LEN;
762
763 /* if there already were last packet chunk, we won't continue */
764 if (nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_LAST)
765 return;
766
767 /* if this is first packet chunk, we need to decide,
768 * if there will be one or more chunks */
769 if (nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_FIRST) {
770 if (prefixes->count <= EIGRP_TLV_MAX_IPv4) {
771 /* there will be only one chunk */
772 flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG
773 + EIGRP_EOT_FLAG;
774 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST;
775 } else {
776 /* there will be more chunks */
777 flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG;
778 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA;
779 }
780 } else {
781 /* this is not first chunk, and we need to decide,
782 * if there will be more chunks */
783 if (prefixes->count <= EIGRP_TLV_MAX_IPv4) {
784 /* this is last chunk */
785 flags = EIGRP_EOT_FLAG;
786 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST;
787 } else {
788 /* there will be more chunks */
789 flags = 0;
790 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA;
791 }
792 }
793
3a45a729 794 ep = eigrp_packet_new(ei->ifp->mtu, nbr);
d62a17ae 795
796 /* Prepare EIGRP Graceful restart UPDATE header */
3a45a729
DS
797 eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp, ep->s, flags,
798 eigrp->sequence_number,
d62a17ae 799 nbr->recv_sequence_number);
800
801 // encode Authentication TLV, if needed
b748db67
DS
802 if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
803 && (ei->params.auth_keychain != NULL)) {
3a45a729 804 length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei);
d62a17ae 805 }
806
9ca66cc7
DS
807 for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
808 if (!rn->info)
809 continue;
810
811 pe = rn->info;
d62a17ae 812 /*
813 * Filtering
814 */
02b45998 815 dest_addr = pe->destination;
71b52ef2
DS
816
817 if (eigrp_update_prefix_apply(eigrp, ei,
818 EIGRP_FILTER_OUT,
819 dest_addr)) {
d62a17ae 820 /* do not send filtered route */
821 zlog_info("Filtered prefix %s won't be sent out.",
02b45998 822 inet_ntoa(dest_addr->u.prefix4));
d62a17ae 823 } else {
824 /* sending route which wasn't filtered */
825 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
826 send_prefixes++;
827 }
828
71b52ef2
DS
829 /*
830 * This makes no sense, Filter out then filter in???
831 * Look into this more - DBS
832 */
833 if (eigrp_update_prefix_apply(eigrp, ei,
834 EIGRP_FILTER_IN,
835 dest_addr)) {
d62a17ae 836 /* do not send filtered route */
837 zlog_info("Filtered prefix %s will be removed.",
02b45998 838 inet_ntoa(dest_addr->u.prefix4));
d62a17ae 839
d62a17ae 840 /* prepare message for FSM */
92035b1d 841 struct eigrp_fsm_action_message fsm_msg;
d62a17ae 842
255ab940 843 struct eigrp_nexthop_entry *entry =
d62a17ae 844 eigrp_prefix_entry_lookup(pe->entries, nbr);
845
92035b1d 846 fsm_msg.packet_type = EIGRP_OPC_UPDATE;
3a45a729 847 fsm_msg.eigrp = eigrp;
7cfa4322 848 fsm_msg.data_type = EIGRP_INT;
92035b1d 849 fsm_msg.adv_router = nbr;
5ca6df78
DS
850 fsm_msg.metrics = pe->reported_metric;
851 /* Set delay to MAX */
852 fsm_msg.metrics.delay = EIGRP_MAX_METRIC;
92035b1d
DS
853 fsm_msg.entry = entry;
854 fsm_msg.prefix = pe;
d62a17ae 855
856 /* send message to FSM */
6118272f 857 eigrp_fsm_event(&fsm_msg);
d62a17ae 858 }
d62a17ae 859
860 /* NULL the pointer */
861 dest_addr = NULL;
862
863 /* delete processed prefix from list */
864 listnode_delete(prefixes, pe);
865
866 /* if there are enough prefixes, send packet */
867 if (send_prefixes >= EIGRP_TLV_MAX_IPv4)
868 break;
869 }
870
871 /* compute Auth digest */
b748db67
DS
872 if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
873 && (ei->params.auth_keychain != NULL)) {
3a45a729 874 eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);
d62a17ae 875 }
876
877 /* EIGRP Checksum */
3a45a729 878 eigrp_packet_checksum(ei, ep->s, length);
d62a17ae 879
880 ep->length = length;
881 ep->dst.s_addr = nbr->src.s_addr;
882
883 /*This ack number we await from neighbor*/
3a45a729 884 ep->sequence_number = eigrp->sequence_number;
d62a17ae 885
886 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
887 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
888 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
889
890 /*Put packet to retransmission queue*/
f90f65a2 891 eigrp_fifo_push(nbr->retrans_queue, ep);
d62a17ae 892
893 if (nbr->retrans_queue->count == 1) {
894 eigrp_send_packet_reliably(nbr);
895 }
7f57883e
DS
896}
897
898/**
899 * @fn eigrp_update_send_GR_thread
900 *
d62a17ae 901 * @param[in] thread contains neighbor who would receive
902 * Graceful restart
7f57883e
DS
903 *
904 * @return int always 0
905 *
906 * @par
907 * Function used for sending Graceful restart Update packet
908 * in thread, it is prepared for multiple chunks of packet.
909 *
910 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
911 */
d62a17ae 912int eigrp_update_send_GR_thread(struct thread *thread)
7f57883e 913{
d62a17ae 914 struct eigrp_neighbor *nbr;
915
916 /* get argument from thread */
917 nbr = THREAD_ARG(thread);
918 /* remove this thread pointer */
919 nbr->t_nbr_send_gr = NULL;
920
921 /* if there is packet waiting in queue,
922 * schedule this thread again with small delay */
923 if (nbr->retrans_queue->count > 0) {
924 nbr->t_nbr_send_gr = NULL;
925 thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr,
926 10, &nbr->t_nbr_send_gr);
927 return 0;
928 }
929
930 /* send GR EIGRP packet chunk */
931 eigrp_update_send_GR_part(nbr);
932
933 /* if it wasn't last chunk, schedule this thread again */
934 if (nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST) {
935 thread_execute(master, eigrp_update_send_GR_thread, nbr, 0);
936 nbr->t_nbr_send_gr = NULL;
937 }
938
939 return 0;
7f57883e
DS
940}
941
942/**
943 * @fn eigrp_update_send_GR
944 *
9d303b37
DL
945 * @param[in] nbr Neighbor who would receive Graceful
946 * restart
7f57883e
DS
947 * @param[in] gr_type Who executed Graceful restart
948 * @param[in] vty Virtual terminal for log output
949 *
950 * @return void
951 *
952 * @par
953 * Function used for sending Graceful restart Update packet:
954 * Creates Update packet with INIT, RS, EOT flags and include
955 * all route except those filtered
956 */
d62a17ae 957void eigrp_update_send_GR(struct eigrp_neighbor *nbr, enum GR_type gr_type,
958 struct vty *vty)
7f57883e 959{
d62a17ae 960 struct eigrp_prefix_entry *pe2;
d62a17ae 961 struct list *prefixes;
9ca66cc7
DS
962 struct route_node *rn;
963 struct eigrp_interface *ei = nbr->ei;
964 struct eigrp *eigrp = ei->eigrp;
d62a17ae 965
966 if (gr_type == EIGRP_GR_FILTER) {
967 /* function was called after applying filtration */
968 zlog_info(
969 "Neighbor %s (%s) is resync: route configuration changed",
970 inet_ntoa(nbr->src),
9ca66cc7 971 ifindex2ifname(ei->ifp->ifindex, VRF_DEFAULT));
d62a17ae 972 } else if (gr_type == EIGRP_GR_MANUAL) {
973 /* Graceful restart was called manually */
974 zlog_info("Neighbor %s (%s) is resync: manually cleared",
975 inet_ntoa(nbr->src),
9ca66cc7 976 ifindex2ifname(ei->ifp->ifindex, VRF_DEFAULT));
d62a17ae 977
978 if (vty != NULL) {
979 vty_time_print(vty, 0);
980 vty_out(vty,
981 "Neighbor %s (%s) is resync: manually cleared\n",
982 inet_ntoa(nbr->src),
9ca66cc7 983 ifindex2ifname(ei->ifp->ifindex,
d62a17ae 984 VRF_DEFAULT));
985 }
986 }
987
988 prefixes = list_new();
989 /* add all prefixes from topology table to list */
9ca66cc7
DS
990 for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
991 if (!rn->info)
992 continue;
993
994 pe2 = rn->info;
d62a17ae 995 listnode_add(prefixes, pe2);
996 }
997
998 /* save prefixes to neighbor */
999 nbr->nbr_gr_prefixes_send = prefixes;
1000 /* indicate, that this is first GR Update packet chunk */
1001 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_FIRST;
1002 /* execute packet sending in thread */
1003 thread_execute(master, eigrp_update_send_GR_thread, nbr, 0);
1004 nbr->t_nbr_send_gr = NULL;
7f57883e
DS
1005}
1006
1007/**
1008 * @fn eigrp_update_send_interface_GR
1009 *
9d303b37
DL
1010 * @param[in] ei Interface to neighbors of which the GR
1011 * is sent
7f57883e
DS
1012 * @param[in] gr_type Who executed Graceful restart
1013 * @param[in] vty Virtual terminal for log output
1014 *
1015 * @return void
1016 *
1017 * @par
1018 * Function used for sending Graceful restart Update packet
1019 * to all neighbors on specified interface.
1020 */
d62a17ae 1021void eigrp_update_send_interface_GR(struct eigrp_interface *ei,
1022 enum GR_type gr_type, struct vty *vty)
7f57883e 1023{
d62a17ae 1024 struct listnode *node;
1025 struct eigrp_neighbor *nbr;
1026
1027 /* iterate over all neighbors on eigrp interface */
1028 for (ALL_LIST_ELEMENTS_RO(ei->nbrs, node, nbr)) {
1029 /* send GR to neighbor */
1030 eigrp_update_send_GR(nbr, gr_type, vty);
1031 }
7f57883e
DS
1032}
1033
1034/**
1035 * @fn eigrp_update_send_process_GR
1036 *
1037 * @param[in] eigrp EIGRP process
1038 * @param[in] gr_type Who executed Graceful restart
1039 * @param[in] vty Virtual terminal for log output
1040 *
1041 * @return void
1042 *
1043 * @par
1044 * Function used for sending Graceful restart Update packet
1045 * to all neighbors in eigrp process.
1046 */
d62a17ae 1047void eigrp_update_send_process_GR(struct eigrp *eigrp, enum GR_type gr_type,
1048 struct vty *vty)
7f57883e 1049{
d62a17ae 1050 struct listnode *node;
1051 struct eigrp_interface *ei;
1052
1053 /* iterate over all eigrp interfaces */
1054 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
1055 /* send GR to all neighbors on interface */
1056 eigrp_update_send_interface_GR(ei, gr_type, vty);
1057 }
f9e5c9ca 1058}