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