2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "lib_errors.h"
31 #include "ospf6_proto.h"
32 #include "ospf6_lsa.h"
33 #include "ospf6_lsdb.h"
34 #include "ospf6_top.h"
35 #include "ospf6_network.h"
36 #include "ospf6_message.h"
38 #include "ospf6_area.h"
39 #include "ospf6_neighbor.h"
40 #include "ospf6_interface.h"
42 /* for structures and macros ospf6_lsa_examin() needs */
43 #include "ospf6_abr.h"
44 #include "ospf6_asbr.h"
45 #include "ospf6_intra.h"
47 #include "ospf6_flood.h"
50 #include <netinet/ip6.h>
52 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_MESSAGE
, "OSPF6 message");
53 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_PACKET
, "OSPF6 packet");
54 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_FIFO
, "OSPF6 FIFO queue");
56 unsigned char conf_debug_ospf6_message
[6] = {0x03, 0, 0, 0, 0, 0};
57 static const struct message ospf6_message_type_str
[] = {
58 {OSPF6_MESSAGE_TYPE_HELLO
, "Hello"},
59 {OSPF6_MESSAGE_TYPE_DBDESC
, "DbDesc"},
60 {OSPF6_MESSAGE_TYPE_LSREQ
, "LSReq"},
61 {OSPF6_MESSAGE_TYPE_LSUPDATE
, "LSUpdate"},
62 {OSPF6_MESSAGE_TYPE_LSACK
, "LSAck"},
65 /* Minimum (besides the standard OSPF packet header) lengths for OSPF
66 packets of particular types, offset is the "type" field. */
67 const uint16_t ospf6_packet_minlen
[OSPF6_MESSAGE_TYPE_ALL
] = {
70 OSPF6_DB_DESC_MIN_SIZE
,
71 OSPF6_LS_REQ_MIN_SIZE
,
72 OSPF6_LS_UPD_MIN_SIZE
,
73 OSPF6_LS_ACK_MIN_SIZE
};
75 /* Minimum (besides the standard LSA header) lengths for LSAs of particular
76 types, offset is the "LSA function code" portion of "LSA type" field. */
77 const uint16_t ospf6_lsa_minlen
[OSPF6_LSTYPE_SIZE
] = {
79 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE
,
80 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE
,
81 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
82 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
,
83 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
85 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
86 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE
,
87 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
};
91 static void ospf6_header_print(struct ospf6_header
*oh
)
93 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%pI4", oh
->version
,
94 oh
->type
, ntohs(oh
->length
), &oh
->router_id
);
95 zlog_debug(" Area-ID:%pI4 Cksum:%hx Instance-ID:%d", &oh
->area_id
,
96 ntohs(oh
->checksum
), oh
->instance_id
);
99 void ospf6_hello_print(struct ospf6_header
*oh
, int action
)
101 struct ospf6_hello
*hello
;
105 ospf6_header_print(oh
);
106 assert(oh
->type
== OSPF6_MESSAGE_TYPE_HELLO
);
108 hello
= (struct ospf6_hello
*)((caddr_t
)oh
109 + sizeof(struct ospf6_header
));
111 ospf6_options_printbuf(hello
->options
, options
, sizeof(options
));
113 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
114 (unsigned long)ntohl(hello
->interface_id
), hello
->priority
,
116 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
117 ntohs(hello
->hello_interval
), ntohs(hello
->dead_interval
));
118 zlog_debug(" DR:%pI4 BDR:%pI4", &hello
->drouter
, &hello
->bdrouter
);
120 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
121 && action
== OSPF6_ACTION_RECV
)
122 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
123 && action
== OSPF6_ACTION_SEND
)) {
125 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
126 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
127 p
+= sizeof(uint32_t))
128 zlog_debug(" Neighbor: %pI4", (in_addr_t
*)p
);
130 assert(p
== OSPF6_MESSAGE_END(oh
));
134 void ospf6_dbdesc_print(struct ospf6_header
*oh
, int action
)
136 struct ospf6_dbdesc
*dbdesc
;
140 ospf6_header_print(oh
);
141 assert(oh
->type
== OSPF6_MESSAGE_TYPE_DBDESC
);
143 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
144 + sizeof(struct ospf6_header
));
146 ospf6_options_printbuf(dbdesc
->options
, options
, sizeof(options
));
148 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc
->reserved1
,
149 options
, ntohs(dbdesc
->ifmtu
));
150 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc
->reserved2
,
151 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
) ? "I" : "-"),
152 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
) ? "M" : "-"),
153 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
) ? "m" : "s"),
154 (unsigned long)ntohl(dbdesc
->seqnum
));
156 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
157 && action
== OSPF6_ACTION_RECV
)
158 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
159 && action
== OSPF6_ACTION_SEND
)) {
161 for (p
= (char *)((caddr_t
)dbdesc
162 + sizeof(struct ospf6_dbdesc
));
163 p
+ sizeof(struct ospf6_lsa_header
)
164 <= OSPF6_MESSAGE_END(oh
);
165 p
+= sizeof(struct ospf6_lsa_header
))
166 ospf6_lsa_header_print_raw(
167 (struct ospf6_lsa_header
*)p
);
169 assert(p
== OSPF6_MESSAGE_END(oh
));
173 void ospf6_lsreq_print(struct ospf6_header
*oh
, int action
)
177 ospf6_header_print(oh
);
178 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSREQ
);
180 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
181 && action
== OSPF6_ACTION_RECV
)
182 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
183 && action
== OSPF6_ACTION_SEND
)) {
185 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
186 p
+ sizeof(struct ospf6_lsreq_entry
)
187 <= OSPF6_MESSAGE_END(oh
);
188 p
+= sizeof(struct ospf6_lsreq_entry
)) {
189 struct ospf6_lsreq_entry
*e
=
190 (struct ospf6_lsreq_entry
*)p
;
192 zlog_debug(" [%s Id:%pI4 Adv:%pI4]",
193 ospf6_lstype_name(e
->type
), &e
->id
,
197 assert(p
== OSPF6_MESSAGE_END(oh
));
201 void ospf6_lsupdate_print(struct ospf6_header
*oh
, int action
)
203 struct ospf6_lsupdate
*lsupdate
;
207 ospf6_header_print(oh
);
208 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSUPDATE
);
210 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
211 + sizeof(struct ospf6_header
));
213 num
= ntohl(lsupdate
->lsa_number
);
214 zlog_debug(" Number of LSA: %ld", num
);
216 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
217 && action
== OSPF6_ACTION_RECV
)
218 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
219 && action
== OSPF6_ACTION_SEND
)) {
221 for (p
= (char *)((caddr_t
)lsupdate
222 + sizeof(struct ospf6_lsupdate
));
223 p
< OSPF6_MESSAGE_END(oh
)
224 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
225 p
+= OSPF6_LSA_SIZE(p
)) {
226 ospf6_lsa_header_print_raw(
227 (struct ospf6_lsa_header
*)p
);
230 assert(p
== OSPF6_MESSAGE_END(oh
));
234 void ospf6_lsack_print(struct ospf6_header
*oh
, int action
)
238 ospf6_header_print(oh
);
239 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
241 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
242 && action
== OSPF6_ACTION_RECV
)
243 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
244 && action
== OSPF6_ACTION_SEND
)) {
246 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
247 p
+ sizeof(struct ospf6_lsa_header
)
248 <= OSPF6_MESSAGE_END(oh
);
249 p
+= sizeof(struct ospf6_lsa_header
))
250 ospf6_lsa_header_print_raw(
251 (struct ospf6_lsa_header
*)p
);
253 assert(p
== OSPF6_MESSAGE_END(oh
));
257 static struct ospf6_packet
*ospf6_packet_new(size_t size
)
259 struct ospf6_packet
*new;
261 new = XCALLOC(MTYPE_OSPF6_PACKET
, sizeof(struct ospf6_packet
));
262 new->s
= stream_new(size
);
267 static void ospf6_packet_free(struct ospf6_packet
*op
)
272 XFREE(MTYPE_OSPF6_PACKET
, op
);
275 struct ospf6_fifo
*ospf6_fifo_new(void)
277 struct ospf6_fifo
*new;
279 new = XCALLOC(MTYPE_OSPF6_FIFO
, sizeof(struct ospf6_fifo
));
283 /* Add new packet to fifo. */
284 static void ospf6_fifo_push(struct ospf6_fifo
*fifo
, struct ospf6_packet
*op
)
287 fifo
->tail
->next
= op
;
296 /* Add new packet to head of fifo. */
297 static void ospf6_fifo_push_head(struct ospf6_fifo
*fifo
,
298 struct ospf6_packet
*op
)
300 op
->next
= fifo
->head
;
302 if (fifo
->tail
== NULL
)
310 /* Delete first packet from fifo. */
311 static struct ospf6_packet
*ospf6_fifo_pop(struct ospf6_fifo
*fifo
)
313 struct ospf6_packet
*op
;
318 fifo
->head
= op
->next
;
320 if (fifo
->head
== NULL
)
329 /* Return first fifo entry. */
330 static struct ospf6_packet
*ospf6_fifo_head(struct ospf6_fifo
*fifo
)
335 /* Flush ospf packet fifo. */
336 void ospf6_fifo_flush(struct ospf6_fifo
*fifo
)
338 struct ospf6_packet
*op
;
339 struct ospf6_packet
*next
;
341 for (op
= fifo
->head
; op
; op
= next
) {
343 ospf6_packet_free(op
);
345 fifo
->head
= fifo
->tail
= NULL
;
349 /* Free ospf packet fifo. */
350 void ospf6_fifo_free(struct ospf6_fifo
*fifo
)
352 ospf6_fifo_flush(fifo
);
354 XFREE(MTYPE_OSPF6_FIFO
, fifo
);
357 static void ospf6_packet_add(struct ospf6_interface
*oi
,
358 struct ospf6_packet
*op
)
360 /* Add packet to end of queue. */
361 ospf6_fifo_push(oi
->obuf
, op
);
363 /* Debug of packet fifo*/
364 /* ospf_fifo_debug (oi->obuf); */
367 static void ospf6_packet_add_top(struct ospf6_interface
*oi
,
368 struct ospf6_packet
*op
)
370 /* Add packet to head of queue. */
371 ospf6_fifo_push_head(oi
->obuf
, op
);
373 /* Debug of packet fifo*/
374 /* ospf_fifo_debug (oi->obuf); */
377 static void ospf6_packet_delete(struct ospf6_interface
*oi
)
379 struct ospf6_packet
*op
;
381 op
= ospf6_fifo_pop(oi
->obuf
);
384 ospf6_packet_free(op
);
388 static void ospf6_hello_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
389 struct ospf6_interface
*oi
,
390 struct ospf6_header
*oh
)
392 struct ospf6_hello
*hello
;
393 struct ospf6_neighbor
*on
;
396 int neighborchange
= 0;
397 int neighbor_ifindex_change
= 0;
400 struct timeval timestamp
;
402 monotime(×tamp
);
403 hello
= (struct ospf6_hello
*)((caddr_t
)oh
404 + sizeof(struct ospf6_header
));
406 /* HelloInterval check */
407 if (ntohs(hello
->hello_interval
) != oi
->hello_interval
) {
409 "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
410 vrf_id_to_name(oi
->interface
->vrf_id
),
411 oi
->interface
->name
, oi
->hello_interval
,
412 ntohs(hello
->hello_interval
));
416 /* RouterDeadInterval check */
417 if (ntohs(hello
->dead_interval
) != oi
->dead_interval
) {
419 "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
420 vrf_id_to_name(oi
->interface
->vrf_id
),
421 oi
->interface
->name
, oi
->dead_interval
,
422 ntohs(hello
->dead_interval
));
427 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_E
)
428 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_E
)) {
429 zlog_warn("VRF %s: IF %s E-bit mismatch",
430 vrf_id_to_name(oi
->interface
->vrf_id
),
431 oi
->interface
->name
);
435 /* Find neighbor, create if not exist */
436 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
438 on
= ospf6_neighbor_create(oh
->router_id
, oi
);
439 on
->prev_drouter
= on
->drouter
= hello
->drouter
;
440 on
->prev_bdrouter
= on
->bdrouter
= hello
->bdrouter
;
441 on
->priority
= hello
->priority
;
444 /* check latency against hello period */
446 latency
= monotime_since(&on
->last_hello
, NULL
)
447 - (oi
->hello_interval
* 1000000);
448 /* log if latency exceeds the hello period */
449 if (latency
> (oi
->hello_interval
* 1000000))
450 zlog_warn("%s RX %pI4 high latency %" PRId64
"us.", __func__
,
451 &on
->router_id
, latency
);
452 on
->last_hello
= timestamp
;
455 /* Always override neighbor's source address */
456 memcpy(&on
->linklocal_addr
, src
, sizeof(struct in6_addr
));
458 /* Neighbor ifindex check */
459 if (on
->ifindex
!= (ifindex_t
)ntohl(hello
->interface_id
)) {
460 on
->ifindex
= ntohl(hello
->interface_id
);
461 neighbor_ifindex_change
++;
465 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
466 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
467 p
+= sizeof(uint32_t)) {
468 uint32_t *router_id
= (uint32_t *)p
;
470 if (*router_id
== oi
->area
->ospf6
->router_id
)
474 assert(p
== OSPF6_MESSAGE_END(oh
));
476 /* RouterPriority check */
477 if (on
->priority
!= hello
->priority
) {
478 on
->priority
= hello
->priority
;
483 if (on
->drouter
!= hello
->drouter
) {
484 on
->prev_drouter
= on
->drouter
;
485 on
->drouter
= hello
->drouter
;
486 if (on
->prev_drouter
== on
->router_id
487 || on
->drouter
== on
->router_id
)
492 if (on
->bdrouter
!= hello
->bdrouter
) {
493 on
->prev_bdrouter
= on
->bdrouter
;
494 on
->bdrouter
= hello
->bdrouter
;
495 if (on
->prev_bdrouter
== on
->router_id
496 || on
->bdrouter
== on
->router_id
)
500 /* BackupSeen check */
501 if (oi
->state
== OSPF6_INTERFACE_WAITING
) {
502 if (hello
->bdrouter
== on
->router_id
)
504 else if (hello
->drouter
== on
->router_id
505 && hello
->bdrouter
== htonl(0))
511 /* Execute neighbor events */
512 thread_execute(master
, hello_received
, on
, 0);
514 thread_execute(master
, twoway_received
, on
, 0);
516 thread_execute(master
, oneway_received
, on
, 0);
518 /* Schedule interface events */
520 thread_add_event(master
, backup_seen
, oi
, 0, NULL
);
522 thread_add_event(master
, neighbor_change
, oi
, 0, NULL
);
524 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
525 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
528 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
529 struct ospf6_neighbor
*on
)
531 struct ospf6_dbdesc
*dbdesc
;
534 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
535 + sizeof(struct ospf6_header
));
537 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
538 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
539 zlog_debug("Neighbor state less than Init, ignore");
544 case OSPF6_NEIGHBOR_TWOWAY
:
545 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
546 zlog_debug("Neighbor state is 2-Way, ignore");
549 case OSPF6_NEIGHBOR_INIT
:
550 thread_execute(master
, twoway_received
, on
, 0);
551 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
552 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
554 "Neighbor state is not ExStart, ignore");
557 /* else fall through to ExStart */
559 case OSPF6_NEIGHBOR_EXSTART
:
560 /* if neighbor obeys us as our slave, schedule negotiation_done
561 and process LSA Headers. Otherwise, ignore this message */
562 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
563 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
564 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
565 /* execute NegotiationDone */
566 thread_execute(master
, negotiation_done
, on
, 0);
568 /* Record neighbor options */
569 memcpy(on
->options
, dbdesc
->options
,
570 sizeof(on
->options
));
573 "VRF %s: Nbr %s: Negotiation failed",
574 vrf_id_to_name(on
->ospf6_if
->interface
->vrf_id
),
578 /* fall through to exchange */
580 case OSPF6_NEIGHBOR_EXCHANGE
:
581 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
582 sizeof(struct ospf6_dbdesc
))) {
583 /* Duplicated DatabaseDescription is dropped by master
585 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
587 "Duplicated dbdesc discarded by Master, ignore");
591 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
593 "DbDesc recv: Master/Slave bit mismatch Nbr %s",
595 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
600 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
601 zlog_warn("DbDesc recv: Initialize bit mismatch Nbr %s",
603 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
608 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
609 zlog_warn("DbDesc recv: Option field mismatch Nbr %s",
611 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
616 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
618 "DbDesc recv: Sequence number mismatch Nbr %s (%#lx expected)",
619 on
->name
, (unsigned long)on
->dbdesc_seqnum
);
620 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
626 case OSPF6_NEIGHBOR_LOADING
:
627 case OSPF6_NEIGHBOR_FULL
:
628 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
629 sizeof(struct ospf6_dbdesc
))) {
630 /* Duplicated DatabaseDescription is dropped by master
632 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
634 "Duplicated dbdesc discarded by Master, ignore");
639 "DbDesc recv: Not duplicate dbdesc in state %s Nbr %s",
640 ospf6_neighbor_state_str
[on
->state
], on
->name
);
641 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
649 /* Process LSA headers */
650 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
651 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
652 p
+= sizeof(struct ospf6_lsa_header
)) {
653 struct ospf6_lsa
*his
, *mine
;
654 struct ospf6_lsdb
*lsdb
= NULL
;
656 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
658 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
659 zlog_debug("%s", his
->name
);
661 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
662 case OSPF6_SCOPE_LINKLOCAL
:
663 lsdb
= on
->ospf6_if
->lsdb
;
665 case OSPF6_SCOPE_AREA
:
666 lsdb
= on
->ospf6_if
->area
->lsdb
;
669 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
671 case OSPF6_SCOPE_RESERVED
:
672 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
673 zlog_debug("Ignoring LSA of reserved scope");
674 ospf6_lsa_delete(his
);
679 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
680 && (IS_AREA_STUB(on
->ospf6_if
->area
)
681 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
682 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
684 "SeqNumMismatch (E-bit mismatch), discard");
685 ospf6_lsa_delete(his
);
686 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
691 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
692 his
->header
->adv_router
, lsdb
);
694 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
695 zlog_debug("Add request (No database copy)");
696 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
697 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
698 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
699 zlog_debug("Add request (Received MoreRecent)");
700 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
702 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
703 zlog_debug("Discard (Existing MoreRecent)");
705 ospf6_lsa_delete(his
);
708 assert(p
== OSPF6_MESSAGE_END(oh
));
710 /* Increment sequence number */
713 /* schedule send lsreq */
714 if (on
->request_list
->count
)
715 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
716 &on
->thread_send_lsreq
);
718 THREAD_OFF(on
->thread_send_dbdesc
);
721 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
722 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
723 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
725 on
->thread_send_dbdesc
= NULL
;
726 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
727 &on
->thread_send_dbdesc
);
730 /* save last received dbdesc */
731 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
734 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
735 struct ospf6_neighbor
*on
)
737 struct ospf6_dbdesc
*dbdesc
;
740 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
741 + sizeof(struct ospf6_header
));
743 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
744 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
745 zlog_debug("Neighbor state less than Init, ignore");
750 case OSPF6_NEIGHBOR_TWOWAY
:
751 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
752 zlog_debug("Neighbor state is 2-Way, ignore");
755 case OSPF6_NEIGHBOR_INIT
:
756 thread_execute(master
, twoway_received
, on
, 0);
757 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
758 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
760 "Neighbor state is not ExStart, ignore");
763 /* else fall through to ExStart */
765 case OSPF6_NEIGHBOR_EXSTART
:
766 /* If the neighbor is Master, act as Slave. Schedule
768 and process LSA Headers. Otherwise, ignore this message */
769 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
770 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
771 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
773 == sizeof(struct ospf6_header
)
774 + sizeof(struct ospf6_dbdesc
)) {
775 /* set the master/slave bit to slave */
776 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
778 /* set the DD sequence number to one specified by master
780 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
782 /* schedule NegotiationDone */
783 thread_execute(master
, negotiation_done
, on
, 0);
785 /* Record neighbor options */
786 memcpy(on
->options
, dbdesc
->options
,
787 sizeof(on
->options
));
790 "VRF %s: Nbr %s Negotiation failed",
791 vrf_id_to_name(on
->ospf6_if
->interface
->vrf_id
),
797 case OSPF6_NEIGHBOR_EXCHANGE
:
798 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
799 sizeof(struct ospf6_dbdesc
))) {
800 /* Duplicated DatabaseDescription causes slave to
802 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
804 "Duplicated dbdesc causes retransmit");
805 THREAD_OFF(on
->thread_send_dbdesc
);
806 on
->thread_send_dbdesc
= NULL
;
807 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
808 &on
->thread_send_dbdesc
);
812 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
814 "DbDesc slave recv: Master/Slave bit mismatch Nbr %s",
816 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
821 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
823 "DbDesc slave recv: Initialize bit mismatch Nbr %s",
825 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
830 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
832 "DbDesc slave recv: Option field mismatch Nbr %s",
834 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
839 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
841 "DbDesc slave recv: Sequence number mismatch Nbr %s (%#lx expected)",
842 on
->name
, (unsigned long)on
->dbdesc_seqnum
+ 1);
843 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
849 case OSPF6_NEIGHBOR_LOADING
:
850 case OSPF6_NEIGHBOR_FULL
:
851 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
852 sizeof(struct ospf6_dbdesc
))) {
853 /* Duplicated DatabaseDescription causes slave to
855 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
857 "Duplicated dbdesc causes retransmit");
858 THREAD_OFF(on
->thread_send_dbdesc
);
859 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
860 &on
->thread_send_dbdesc
);
865 "DbDesc slave recv: Not duplicate dbdesc in state %s Nbr %s",
866 ospf6_neighbor_state_str
[on
->state
], on
->name
);
867 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
875 /* Process LSA headers */
876 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
877 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
878 p
+= sizeof(struct ospf6_lsa_header
)) {
879 struct ospf6_lsa
*his
, *mine
;
880 struct ospf6_lsdb
*lsdb
= NULL
;
882 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
884 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
885 case OSPF6_SCOPE_LINKLOCAL
:
886 lsdb
= on
->ospf6_if
->lsdb
;
888 case OSPF6_SCOPE_AREA
:
889 lsdb
= on
->ospf6_if
->area
->lsdb
;
892 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
894 case OSPF6_SCOPE_RESERVED
:
895 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
896 zlog_debug("Ignoring LSA of reserved scope");
897 ospf6_lsa_delete(his
);
902 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
903 && (IS_AREA_STUB(on
->ospf6_if
->area
)
904 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
905 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
906 zlog_debug("E-bit mismatch with LSA Headers");
907 ospf6_lsa_delete(his
);
908 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
913 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
914 his
->header
->adv_router
, lsdb
);
915 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
916 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
917 zlog_debug("Add request-list: %s", his
->name
);
918 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
920 ospf6_lsa_delete(his
);
923 assert(p
== OSPF6_MESSAGE_END(oh
));
925 /* Set sequence number to Master's */
926 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
928 /* schedule send lsreq */
929 if (on
->request_list
->count
)
930 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
931 &on
->thread_send_lsreq
);
933 THREAD_OFF(on
->thread_send_dbdesc
);
934 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
935 &on
->thread_send_dbdesc
);
937 /* save last received dbdesc */
938 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
941 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
942 struct ospf6_interface
*oi
,
943 struct ospf6_header
*oh
)
945 struct ospf6_neighbor
*on
;
946 struct ospf6_dbdesc
*dbdesc
;
948 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
950 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
951 zlog_debug("Neighbor not found, ignore");
955 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
956 + sizeof(struct ospf6_header
));
958 /* Interface MTU check */
959 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
960 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
961 vrf_id_to_name(oi
->interface
->vrf_id
),
962 oi
->interface
->name
, oi
->ifmtu
, ntohs(dbdesc
->ifmtu
));
966 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
967 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
969 "Non-0 reserved field in %s's DbDesc, correct",
971 dbdesc
->reserved1
= 0;
972 dbdesc
->reserved2
= 0;
977 if (ntohl(oh
->router_id
) < ntohl(oi
->area
->ospf6
->router_id
))
978 ospf6_dbdesc_recv_master(oh
, on
);
979 else if (ntohl(oi
->area
->ospf6
->router_id
) < ntohl(oh
->router_id
))
980 ospf6_dbdesc_recv_slave(oh
, on
);
982 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
983 zlog_debug("Can't decide which is master, ignore");
987 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
988 struct ospf6_interface
*oi
,
989 struct ospf6_header
*oh
)
991 struct ospf6_neighbor
*on
;
993 struct ospf6_lsreq_entry
*e
;
994 struct ospf6_lsdb
*lsdb
= NULL
;
995 struct ospf6_lsa
*lsa
;
997 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
999 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1000 zlog_debug("Neighbor not found, ignore");
1004 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1005 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1006 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1007 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1008 zlog_debug("Neighbor state less than Exchange, ignore");
1014 /* Process each request */
1015 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1016 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
1017 p
+= sizeof(struct ospf6_lsreq_entry
)) {
1018 e
= (struct ospf6_lsreq_entry
*)p
;
1020 switch (OSPF6_LSA_SCOPE(e
->type
)) {
1021 case OSPF6_SCOPE_LINKLOCAL
:
1022 lsdb
= on
->ospf6_if
->lsdb
;
1024 case OSPF6_SCOPE_AREA
:
1025 lsdb
= on
->ospf6_if
->area
->lsdb
;
1027 case OSPF6_SCOPE_AS
:
1028 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1031 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1032 zlog_debug("Ignoring LSA of reserved scope");
1037 /* Find database copy */
1038 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
1041 "Can't find requested lsa [%s Id:%pI4 Adv:%pI4] send badLSReq",
1042 ospf6_lstype_name(e
->type
), &e
->id
,
1044 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
1048 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
1051 assert(p
== OSPF6_MESSAGE_END(oh
));
1053 /* schedule send lsupdate */
1054 THREAD_OFF(on
->thread_send_lsupdate
);
1055 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
1056 &on
->thread_send_lsupdate
);
1059 /* Verify, that the specified memory area contains exactly N valid IPv6
1060 prefixes as specified by RFC5340, A.4.1. */
1061 static unsigned ospf6_prefixes_examin(
1062 struct ospf6_prefix
*current
, /* start of buffer */
1064 const uint32_t req_num_pfxs
/* always compared with the actual number
1068 uint8_t requested_pfx_bytes
;
1069 uint32_t real_num_pfxs
= 0;
1072 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
1073 zlog_warn("%s: undersized IPv6 prefix header",
1077 /* safe to look deeper */
1078 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
1079 zlog_warn("%s: invalid PrefixLength (%u bits)",
1080 __func__
, current
->prefix_length
);
1083 /* covers both fixed- and variable-sized fields */
1084 requested_pfx_bytes
=
1085 OSPF6_PREFIX_MIN_SIZE
1086 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
1087 if (requested_pfx_bytes
> length
) {
1088 zlog_warn("%s: undersized IPv6 prefix", __func__
);
1092 length
-= requested_pfx_bytes
;
1093 current
= (struct ospf6_prefix
*)((caddr_t
)current
1094 + requested_pfx_bytes
);
1097 if (real_num_pfxs
!= req_num_pfxs
) {
1099 "%s: IPv6 prefix number mismatch (%u required, %u real)",
1100 __func__
, req_num_pfxs
, real_num_pfxs
);
1106 /* Verify an LSA to have a valid length and dispatch further (where
1107 appropriate) to check if the contents, including nested IPv6 prefixes,
1108 is properly sized/aligned within the LSA. Note that this function gets
1109 LSA type in network byte order, uses in host byte order and passes to
1110 ospf6_lstype_name() in network byte order again. */
1111 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
1112 const uint16_t lsalen
,
1113 const uint8_t headeronly
)
1115 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1116 struct ospf6_as_external_lsa
*as_external_lsa
;
1117 struct ospf6_link_lsa
*link_lsa
;
1118 unsigned exp_length
;
1122 /* In case an additional minimum length constraint is defined for
1124 LSA type, make sure that this constraint is met. */
1125 lsatype
= ntohs(lsah
->type
);
1126 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
1127 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
1128 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
1129 zlog_warn("%s: undersized (%u B) LSA", __func__
, lsalen
);
1133 case OSPF6_LSTYPE_ROUTER
:
1134 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
1136 by N>=0 interface descriptions. */
1137 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
1138 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
1140 "%s: Router LSA interface description alignment error",
1145 case OSPF6_LSTYPE_NETWORK
:
1146 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1147 followed by N>=0 attached router descriptions. */
1148 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
1149 - OSPF6_NETWORK_LSA_MIN_SIZE
)
1150 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
1152 "%s: Network LSA router description alignment error",
1157 case OSPF6_LSTYPE_INTER_PREFIX
:
1158 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1160 followed by 3-4 fields of a single IPv6 prefix. */
1163 return ospf6_prefixes_examin(
1164 (struct ospf6_prefix
1165 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
1166 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
1167 lsalen
- OSPF6_LSA_HEADER_SIZE
1168 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
1170 case OSPF6_LSTYPE_INTER_ROUTER
:
1171 /* RFC5340 A.4.6, fixed-size LSA. */
1173 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1174 zlog_warn("%s: Inter Router LSA oversized (%u B) LSA",
1179 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1180 case OSPF6_LSTYPE_TYPE_7
:
1181 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1183 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1185 16 bytes of forwarding address, 4 bytes of external route
1187 4 bytes of referenced link state ID. */
1191 (struct ospf6_as_external_lsa
1192 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1194 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1195 /* To find out if the last optional field (Referenced Link State
1197 assumed in this LSA, we need to access fixed fields of the
1199 prefix before ospf6_prefix_examin() confirms its sizing. */
1200 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1202 "%s: AS External undersized (%u B) LSA header",
1206 /* forwarding address */
1207 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1209 /* external route tag */
1210 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1212 /* referenced link state ID */
1213 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1215 /* All the fixed-size fields (mandatory and optional) must fit.
1217 this check does not include any IPv6 prefix fields. */
1218 if (exp_length
> lsalen
) {
1220 "%s: AS External undersized (%u B) LSA header",
1224 /* The last call completely covers the remainder (IPv6 prefix).
1226 return ospf6_prefixes_examin(
1227 (struct ospf6_prefix
1228 *)((caddr_t
)as_external_lsa
1229 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1230 lsalen
- exp_length
, 1);
1231 case OSPF6_LSTYPE_LINK
:
1232 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1234 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1237 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1238 + OSPF6_LSA_HEADER_SIZE
);
1239 return ospf6_prefixes_examin(
1240 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1241 + OSPF6_LINK_LSA_MIN_SIZE
),
1242 lsalen
- OSPF6_LSA_HEADER_SIZE
1243 - OSPF6_LINK_LSA_MIN_SIZE
,
1244 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1246 case OSPF6_LSTYPE_INTRA_PREFIX
:
1247 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1249 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1254 (struct ospf6_intra_prefix_lsa
1255 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1256 return ospf6_prefixes_examin(
1257 (struct ospf6_prefix
1258 *)((caddr_t
)intra_prefix_lsa
1259 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1260 lsalen
- OSPF6_LSA_HEADER_SIZE
1261 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1262 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1265 /* No additional validation is possible for unknown LSA types, which are
1266 themselves valid in OPSFv3, hence the default decision is to accept.
1271 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1272 includes verification of LSA blocks length/alignment and dispatching
1273 of deeper-level checks. */
1275 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1276 size_t length
, const uint8_t headeronly
,
1277 /* When declared_num_lsas is not 0, compare it to the real
1279 and treat the difference as an error. */
1280 const uint32_t declared_num_lsas
)
1282 uint32_t counted_lsas
= 0;
1286 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1288 "%s: undersized (%zu B) trailing (#%u) LSA header",
1289 __func__
, length
, counted_lsas
);
1292 /* save on ntohs() calls here and in the LSA validator */
1293 lsalen
= OSPF6_LSA_SIZE(lsah
);
1294 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1296 "%s: malformed LSA header #%u, declared length is %u B",
1297 __func__
, counted_lsas
, lsalen
);
1301 /* less checks here and in ospf6_lsa_examin() */
1302 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1304 "%s: anomaly in header-only %s LSA #%u",
1305 __func__
, ospf6_lstype_name(lsah
->type
),
1309 lsah
= (struct ospf6_lsa_header
1311 + OSPF6_LSA_HEADER_SIZE
);
1312 length
-= OSPF6_LSA_HEADER_SIZE
;
1314 /* make sure the input buffer is deep enough before
1316 if (lsalen
> length
) {
1318 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1319 __func__
, ospf6_lstype_name(lsah
->type
),
1320 counted_lsas
, lsalen
, length
);
1323 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1324 zlog_warn("%s: anomaly in %s LSA #%u", __func__
,
1325 ospf6_lstype_name(lsah
->type
),
1329 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1336 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1337 zlog_warn("%s: #LSAs declared (%u) does not match actual (%u)",
1338 __func__
, declared_num_lsas
, counted_lsas
);
1344 /* Verify a complete OSPF packet for proper sizing/alignment. */
1345 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1346 const unsigned bytesonwire
)
1348 struct ospf6_lsupdate
*lsupd
;
1351 /* length, 1st approximation */
1352 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1353 zlog_warn("%s: undersized (%u B) packet", __func__
,
1357 /* Now it is safe to access header fields. */
1358 if (bytesonwire
!= ntohs(oh
->length
)) {
1359 zlog_warn("%s: %s packet length error (%u real, %u declared)",
1361 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1362 bytesonwire
, ntohs(oh
->length
));
1366 if (oh
->version
!= OSPFV3_VERSION
) {
1367 zlog_warn("%s: invalid (%u) protocol version", __func__
,
1371 /* length, 2nd approximation */
1372 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1374 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1375 zlog_warn("%s: undersized (%u B) %s packet", __func__
,
1377 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1380 /* type-specific deeper validation */
1382 case OSPF6_MESSAGE_TYPE_HELLO
:
1383 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1385 by N>=0 router-IDs. */
1387 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1390 zlog_warn("%s: alignment error in %s packet", __func__
,
1391 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1393 case OSPF6_MESSAGE_TYPE_DBDESC
:
1394 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1396 by N>=0 header-only LSAs. */
1397 test
= ospf6_lsaseq_examin(
1398 (struct ospf6_lsa_header
*)((caddr_t
)oh
1400 + OSPF6_DB_DESC_MIN_SIZE
),
1401 bytesonwire
- OSPF6_HEADER_SIZE
1402 - OSPF6_DB_DESC_MIN_SIZE
,
1405 case OSPF6_MESSAGE_TYPE_LSREQ
:
1406 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1408 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1409 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1411 zlog_warn("%s: alignment error in %s packet", __func__
,
1412 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1414 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1415 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1417 by N>=0 full LSAs (with N declared beforehand). */
1418 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1419 + OSPF6_HEADER_SIZE
);
1420 test
= ospf6_lsaseq_examin(
1421 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1422 + OSPF6_LS_UPD_MIN_SIZE
),
1423 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1424 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1427 case OSPF6_MESSAGE_TYPE_LSACK
:
1428 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1429 test
= ospf6_lsaseq_examin(
1430 (struct ospf6_lsa_header
*)((caddr_t
)oh
1432 + OSPF6_LS_ACK_MIN_SIZE
),
1433 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1437 zlog_warn("%s: invalid (%u) message type", __func__
, oh
->type
);
1441 zlog_warn("%s: anomaly in %s packet", __func__
,
1442 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1446 /* Verify particular fields of otherwise correct received OSPF packet to
1447 meet the requirements of RFC. */
1448 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1449 struct ospf6_header
*oh
,
1450 const unsigned bytesonwire
)
1453 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1457 if (oh
->area_id
!= oi
->area
->area_id
) {
1458 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1460 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1461 vrf_id_to_name(oi
->interface
->vrf_id
),
1462 oi
->interface
->name
);
1465 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
1466 vrf_id_to_name(oi
->interface
->vrf_id
),
1467 oi
->interface
->name
, &oi
->area
->area_id
,
1472 /* Instance-ID check */
1473 if (oh
->instance_id
!= oi
->instance_id
) {
1475 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1476 vrf_id_to_name(oi
->interface
->vrf_id
),
1477 oi
->interface
->name
, oi
->instance_id
, oh
->instance_id
);
1481 /* Router-ID check */
1482 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1483 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1484 vrf_id_to_name(oi
->interface
->vrf_id
),
1485 oi
->interface
->name
, &oh
->router_id
);
1491 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1492 struct ospf6_interface
*oi
,
1493 struct ospf6_header
*oh
)
1495 struct ospf6_neighbor
*on
;
1496 struct ospf6_lsupdate
*lsupdate
;
1499 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1501 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1502 zlog_debug("Neighbor not found, ignore");
1506 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1507 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1508 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1509 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1510 zlog_debug("Neighbor state less than Exchange, ignore");
1514 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1515 + sizeof(struct ospf6_header
));
1520 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1521 p
< OSPF6_MESSAGE_END(oh
)
1522 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1523 p
+= OSPF6_LSA_SIZE(p
)) {
1524 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1527 assert(p
== OSPF6_MESSAGE_END(oh
));
1530 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1531 struct ospf6_interface
*oi
,
1532 struct ospf6_header
*oh
)
1534 struct ospf6_neighbor
*on
;
1536 struct ospf6_lsa
*his
, *mine
;
1537 struct ospf6_lsdb
*lsdb
= NULL
;
1539 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1541 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1543 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1544 zlog_debug("Neighbor not found, ignore");
1548 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1549 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1550 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1551 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1552 zlog_debug("Neighbor state less than Exchange, ignore");
1558 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1559 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1560 p
+= sizeof(struct ospf6_lsa_header
)) {
1561 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1563 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1564 case OSPF6_SCOPE_LINKLOCAL
:
1565 lsdb
= on
->ospf6_if
->lsdb
;
1567 case OSPF6_SCOPE_AREA
:
1568 lsdb
= on
->ospf6_if
->area
->lsdb
;
1570 case OSPF6_SCOPE_AS
:
1571 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1573 case OSPF6_SCOPE_RESERVED
:
1574 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1575 zlog_debug("Ignoring LSA of reserved scope");
1576 ospf6_lsa_delete(his
);
1581 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1582 zlog_debug("%s acknowledged by %s", his
->name
,
1585 /* Find database copy */
1586 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1587 his
->header
->adv_router
, lsdb
);
1589 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1590 zlog_debug("No database copy");
1591 ospf6_lsa_delete(his
);
1595 /* Check if the LSA is on his retrans-list */
1596 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1597 his
->header
->adv_router
,
1600 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1601 zlog_debug("Not on %s's retrans-list",
1603 ospf6_lsa_delete(his
);
1607 if (ospf6_lsa_compare(his
, mine
) != 0) {
1608 /* Log this questionable acknowledgement,
1609 and examine the next one. */
1610 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1611 zlog_debug("Questionable acknowledgement");
1612 ospf6_lsa_delete(his
);
1616 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1618 "Acknowledged, remove from %s's retrans-list",
1621 ospf6_decrement_retrans_count(mine
);
1622 if (OSPF6_LSA_IS_MAXAGE(mine
))
1623 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1624 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1625 ospf6_lsa_delete(his
);
1628 assert(p
== OSPF6_MESSAGE_END(oh
));
1631 static uint8_t *recvbuf
= NULL
;
1632 static uint8_t *sendbuf
= NULL
;
1633 static unsigned int iobuflen
= 0;
1635 int ospf6_iobuf_size(unsigned int size
)
1637 uint8_t *recvnew
, *sendnew
;
1639 if (size
<= iobuflen
)
1642 recvnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1643 sendnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1645 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1646 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1654 void ospf6_message_terminate(void)
1656 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1657 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1662 enum ospf6_read_return_enum
{
1664 OSPF6_READ_CONTINUE
,
1667 static int ospf6_read_helper(int sockfd
, struct ospf6
*ospf6
)
1670 struct in6_addr src
, dst
;
1672 struct iovec iovector
[2];
1673 struct ospf6_interface
*oi
;
1674 struct ospf6_header
*oh
;
1677 memset(&src
, 0, sizeof(src
));
1678 memset(&dst
, 0, sizeof(dst
));
1680 memset(recvbuf
, 0, iobuflen
);
1681 iovector
[0].iov_base
= recvbuf
;
1682 iovector
[0].iov_len
= iobuflen
;
1683 iovector
[1].iov_base
= NULL
;
1684 iovector
[1].iov_len
= 0;
1686 /* receive message */
1687 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
, sockfd
);
1689 return OSPF6_READ_ERROR
;
1691 if ((uint
)len
> iobuflen
) {
1692 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1693 return OSPF6_READ_ERROR
;
1696 oi
= ospf6_interface_lookup_by_ifindex(ifindex
, ospf6
->vrf_id
);
1697 if (oi
== NULL
|| oi
->area
== NULL
1698 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1699 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1701 zlog_debug("Message received on disabled interface");
1702 return OSPF6_READ_CONTINUE
;
1704 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1705 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1707 zlog_debug("%s: Ignore message on passive interface %s",
1708 __func__
, oi
->interface
->name
);
1709 return OSPF6_READ_CONTINUE
;
1713 * Drop packet destined to another VRF.
1714 * This happens when raw_l3mdev_accept is set to 1.
1716 if (ospf6
->vrf_id
!= oi
->interface
->vrf_id
)
1717 return OSPF6_READ_CONTINUE
;
1719 oh
= (struct ospf6_header
*)recvbuf
;
1720 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1721 return OSPF6_READ_CONTINUE
;
1723 /* Being here means, that no sizing/alignment issues were detected in
1724 the input packet. This renders the additional checks performed below
1725 and also in the type-specific dispatching functions a dead code,
1726 which can be dismissed in a cleanup-focused review round later. */
1729 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
)) {
1730 zlog_debug("%s received on %s",
1731 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1732 oi
->interface
->name
);
1733 zlog_debug(" src: %pI6", &src
);
1734 zlog_debug(" dst: %pI6", &dst
);
1737 case OSPF6_MESSAGE_TYPE_HELLO
:
1738 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1740 case OSPF6_MESSAGE_TYPE_DBDESC
:
1741 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1743 case OSPF6_MESSAGE_TYPE_LSREQ
:
1744 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1746 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1747 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1749 case OSPF6_MESSAGE_TYPE_LSACK
:
1750 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1758 case OSPF6_MESSAGE_TYPE_HELLO
:
1759 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1762 case OSPF6_MESSAGE_TYPE_DBDESC
:
1763 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1766 case OSPF6_MESSAGE_TYPE_LSREQ
:
1767 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1770 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1771 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1774 case OSPF6_MESSAGE_TYPE_LSACK
:
1775 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1782 return OSPF6_READ_CONTINUE
;
1785 int ospf6_receive(struct thread
*thread
)
1788 struct ospf6
*ospf6
;
1791 /* add next read thread */
1792 ospf6
= THREAD_ARG(thread
);
1793 sockfd
= THREAD_FD(thread
);
1795 thread_add_read(master
, ospf6_receive
, ospf6
, ospf6
->fd
,
1796 &ospf6
->t_ospf6_receive
);
1798 while (count
< ospf6
->write_oi_count
) {
1800 switch (ospf6_read_helper(sockfd
, ospf6
)) {
1801 case OSPF6_READ_ERROR
:
1803 case OSPF6_READ_CONTINUE
:
1811 static void ospf6_make_header(uint8_t type
, struct ospf6_interface
*oi
,
1814 struct ospf6_header
*oh
;
1816 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1818 oh
->version
= (uint8_t)OSPFV3_VERSION
;
1821 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1822 oh
->area_id
= oi
->area
->area_id
;
1823 oh
->instance_id
= oi
->instance_id
;
1825 stream_forward_endp(s
, OSPF6_HEADER_SIZE
);
1828 static void ospf6_fill_header(struct ospf6_interface
*oi
, struct stream
*s
,
1831 struct ospf6_header
*oh
;
1833 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1835 oh
->length
= htons(length
);
1838 static void ospf6_fill_lsupdate_header(struct stream
*s
, uint32_t lsa_num
)
1840 struct ospf6_header
*oh
;
1841 struct ospf6_lsupdate
*lsu
;
1843 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1845 lsu
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1846 + sizeof(struct ospf6_header
));
1847 lsu
->lsa_number
= htonl(lsa_num
);
1850 static uint32_t ospf6_packet_max(struct ospf6_interface
*oi
)
1852 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
1853 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
1856 static uint16_t ospf6_make_hello(struct ospf6_interface
*oi
, struct stream
*s
)
1858 struct listnode
*node
, *nnode
;
1859 struct ospf6_neighbor
*on
;
1860 uint16_t length
= OSPF6_HELLO_MIN_SIZE
;
1862 stream_putl(s
, oi
->interface
->ifindex
);
1863 stream_putc(s
, oi
->priority
);
1864 stream_putc(s
, oi
->area
->options
[0]);
1865 stream_putc(s
, oi
->area
->options
[1]);
1866 stream_putc(s
, oi
->area
->options
[2]);
1867 stream_putw(s
, oi
->hello_interval
);
1868 stream_putw(s
, oi
->dead_interval
);
1869 stream_put_ipv4(s
, oi
->drouter
);
1870 stream_put_ipv4(s
, oi
->bdrouter
);
1872 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1873 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
1876 if ((length
+ sizeof(uint32_t) + OSPF6_HEADER_SIZE
)
1877 > ospf6_packet_max(oi
)) {
1878 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
1881 "sending Hello message: exceeds I/F MTU");
1885 stream_put_ipv4(s
, on
->router_id
);
1886 length
+= sizeof(uint32_t);
1892 static int ospf6_write(struct thread
*thread
)
1894 struct ospf6
*ospf6
= THREAD_ARG(thread
);
1895 struct ospf6_interface
*oi
;
1896 struct ospf6_interface
*last_serviced_oi
= NULL
;
1897 struct ospf6_header
*oh
;
1898 struct ospf6_packet
*op
;
1899 struct listnode
*node
;
1900 char srcname
[64], dstname
[64];
1901 struct iovec iovector
[2];
1904 int64_t latency
= 0;
1905 struct timeval timestamp
;
1907 if (ospf6
->fd
< 0) {
1908 zlog_warn("ospf6_write failed to send, fd %d", ospf6
->fd
);
1912 node
= listhead(ospf6
->oi_write_q
);
1914 oi
= listgetdata(node
);
1916 while ((pkt_count
< ospf6
->write_oi_count
) && oi
1917 && (last_serviced_oi
!= oi
)) {
1919 op
= ospf6_fifo_head(oi
->obuf
);
1921 assert(op
->length
>= OSPF6_HEADER_SIZE
);
1923 iovector
[0].iov_base
= (caddr_t
)stream_pnt(op
->s
);
1924 iovector
[0].iov_len
= op
->length
;
1925 iovector
[1].iov_base
= NULL
;
1926 iovector
[1].iov_len
= 0;
1928 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
1930 len
= ospf6_sendmsg(oi
->linklocal_addr
, &op
->dst
,
1931 oi
->interface
->ifindex
, iovector
,
1933 if (len
!= op
->length
)
1934 flog_err(EC_LIB_DEVELOPMENT
,
1935 "Could not send entire message");
1937 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)) {
1938 inet_ntop(AF_INET6
, &op
->dst
, dstname
, sizeof(dstname
));
1939 inet_ntop(AF_INET6
, oi
->linklocal_addr
, srcname
,
1941 zlog_debug("%s send on %s",
1942 lookup_msg(ospf6_message_type_str
, oh
->type
,
1944 oi
->interface
->name
);
1945 zlog_debug(" src: %s", srcname
);
1946 zlog_debug(" dst: %s", dstname
);
1949 case OSPF6_MESSAGE_TYPE_HELLO
:
1950 monotime(×tamp
);
1952 latency
= monotime_since(&oi
->last_hello
, NULL
)
1953 - (oi
->hello_interval
* 1000000);
1955 /* log if latency exceeds the hello period */
1956 if (latency
> (oi
->hello_interval
* 1000000))
1957 zlog_warn("%s hello TX high latency %" PRId64
1960 oi
->last_hello
= timestamp
;
1962 ospf6_hello_print(oh
, OSPF6_ACTION_SEND
);
1964 case OSPF6_MESSAGE_TYPE_DBDESC
:
1966 ospf6_dbdesc_print(oh
, OSPF6_ACTION_SEND
);
1968 case OSPF6_MESSAGE_TYPE_LSREQ
:
1970 ospf6_lsreq_print(oh
, OSPF6_ACTION_SEND
);
1972 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1974 ospf6_lsupdate_print(oh
, OSPF6_ACTION_SEND
);
1976 case OSPF6_MESSAGE_TYPE_LSACK
:
1978 ospf6_lsack_print(oh
, OSPF6_ACTION_SEND
);
1981 zlog_debug("Unknown message");
1985 /* Now delete packet from queue. */
1986 ospf6_packet_delete(oi
);
1988 /* Move this interface to the tail of write_q to
1989 serve everyone in a round robin fashion */
1990 list_delete_node(ospf6
->oi_write_q
, node
);
1991 if (ospf6_fifo_head(oi
->obuf
) == NULL
) {
1993 last_serviced_oi
= NULL
;
1996 listnode_add(ospf6
->oi_write_q
, oi
);
1999 /* Setup to service from the head of the queue again */
2000 if (!list_isempty(ospf6
->oi_write_q
)) {
2001 node
= listhead(ospf6
->oi_write_q
);
2002 oi
= listgetdata(node
);
2006 /* If packets still remain in queue, call write thread. */
2007 if (!list_isempty(ospf6
->oi_write_q
))
2008 thread_add_write(master
, ospf6_write
, ospf6
, ospf6
->fd
,
2014 int ospf6_hello_send(struct thread
*thread
)
2016 struct ospf6_interface
*oi
;
2017 struct ospf6_packet
*op
;
2018 uint16_t length
= OSPF6_HEADER_SIZE
;
2020 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2021 oi
->thread_send_hello
= (struct thread
*)NULL
;
2023 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
2024 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND_HDR
))
2025 zlog_debug("Unable to send Hello on down interface %s",
2026 oi
->interface
->name
);
2030 op
= ospf6_packet_new(oi
->ifmtu
);
2032 ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO
, oi
, op
->s
);
2034 /* Prepare OSPF Hello body */
2035 length
+= ospf6_make_hello(oi
, op
->s
);
2036 if (length
== OSPF6_HEADER_SIZE
) {
2037 /* Hello overshooting MTU */
2038 ospf6_packet_free(op
);
2042 /* Fill OSPF header. */
2043 ospf6_fill_header(oi
, op
->s
, length
);
2045 /* Set packet length. */
2046 op
->length
= length
;
2048 op
->dst
= allspfrouters6
;
2050 /* Add packet to the top of the interface output queue, so that they
2051 * can't get delayed by things like long queues of LS Update packets
2053 ospf6_packet_add_top(oi
, op
);
2055 /* set next thread */
2056 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
2057 &oi
->thread_send_hello
);
2059 OSPF6_MESSAGE_WRITE_ON(oi
);
2064 static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor
*on
, struct stream
*s
)
2066 uint16_t length
= OSPF6_DB_DESC_MIN_SIZE
;
2067 struct ospf6_lsa
*lsa
, *lsanext
;
2069 /* if this is initial one, initialize sequence number for DbDesc */
2070 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
2071 && (on
->dbdesc_seqnum
== 0)) {
2072 on
->dbdesc_seqnum
= monotime(NULL
);
2076 stream_putc(s
, 0); /* reserved 1 */
2077 stream_putc(s
, on
->ospf6_if
->area
->options
[0]);
2078 stream_putc(s
, on
->ospf6_if
->area
->options
[1]);
2079 stream_putc(s
, on
->ospf6_if
->area
->options
[2]);
2080 stream_putw(s
, on
->ospf6_if
->ifmtu
);
2081 stream_putc(s
, 0); /* reserved 2 */
2082 stream_putc(s
, on
->dbdesc_bits
);
2083 stream_putl(s
, on
->dbdesc_seqnum
);
2085 /* if this is not initial one, set LSA headers in dbdesc */
2086 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
2087 for (ALL_LSDB(on
->dbdesc_list
, lsa
, lsanext
)) {
2088 ospf6_lsa_age_update_to_send(lsa
,
2089 on
->ospf6_if
->transdelay
);
2092 if ((length
+ sizeof(struct ospf6_lsa_header
)
2093 + OSPF6_HEADER_SIZE
)
2094 > ospf6_packet_max(on
->ospf6_if
)) {
2095 ospf6_lsa_unlock(lsa
);
2097 ospf6_lsa_unlock(lsanext
);
2100 stream_put(s
, lsa
->header
,
2101 sizeof(struct ospf6_lsa_header
));
2102 length
+= sizeof(struct ospf6_lsa_header
);
2108 int ospf6_dbdesc_send(struct thread
*thread
)
2110 struct ospf6_neighbor
*on
;
2111 uint16_t length
= OSPF6_HEADER_SIZE
;
2112 struct ospf6_packet
*op
;
2114 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2115 on
->thread_send_dbdesc
= (struct thread
*)NULL
;
2117 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
2118 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND
))
2120 "Quit to send DbDesc to neighbor %s state %s",
2121 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
2125 /* set next thread if master */
2126 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
2127 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
2128 on
->ospf6_if
->rxmt_interval
,
2129 &on
->thread_send_dbdesc
);
2131 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2132 ospf6_make_header(OSPF6_MESSAGE_TYPE_DBDESC
, on
->ospf6_if
, op
->s
);
2134 length
+= ospf6_make_dbdesc(on
, op
->s
);
2135 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2137 /* Set packet length. */
2138 op
->length
= length
;
2140 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2141 op
->dst
= allspfrouters6
;
2143 op
->dst
= on
->linklocal_addr
;
2145 ospf6_packet_add(on
->ospf6_if
, op
);
2147 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2152 int ospf6_dbdesc_send_newone(struct thread
*thread
)
2154 struct ospf6_neighbor
*on
;
2155 struct ospf6_lsa
*lsa
, *lsanext
;
2156 unsigned int size
= 0;
2158 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2159 ospf6_lsdb_remove_all(on
->dbdesc_list
);
2161 /* move LSAs from summary_list to dbdesc_list (within neighbor
2163 so that ospf6_send_dbdesc () can send those LSAs */
2164 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
2165 for (ALL_LSDB(on
->summary_list
, lsa
, lsanext
)) {
2166 /* if stub area then don't advertise AS-External LSAs */
2167 if ((IS_AREA_STUB(on
->ospf6_if
->area
)
2168 || IS_AREA_NSSA(on
->ospf6_if
->area
))
2169 && ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
2170 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2174 if (size
+ sizeof(struct ospf6_lsa_header
)
2175 > ospf6_packet_max(on
->ospf6_if
)) {
2176 ospf6_lsa_unlock(lsa
);
2178 ospf6_lsa_unlock(lsanext
);
2182 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
2183 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2184 size
+= sizeof(struct ospf6_lsa_header
);
2187 if (on
->summary_list
->count
== 0)
2188 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
2190 /* If slave, More bit check must be done here */
2191 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
2192 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
2193 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
2194 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
2196 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
2200 static uint16_t ospf6_make_lsreq(struct ospf6_neighbor
*on
, struct stream
*s
)
2202 uint16_t length
= 0;
2203 struct ospf6_lsa
*lsa
, *lsanext
, *last_req
= NULL
;
2205 for (ALL_LSDB(on
->request_list
, lsa
, lsanext
)) {
2206 if ((length
+ OSPF6_HEADER_SIZE
)
2207 > ospf6_packet_max(on
->ospf6_if
)) {
2208 ospf6_lsa_unlock(lsa
);
2210 ospf6_lsa_unlock(lsanext
);
2213 stream_putw(s
, 0); /* reserved */
2214 stream_putw(s
, ntohs(lsa
->header
->type
));
2215 stream_putl(s
, ntohl(lsa
->header
->id
));
2216 stream_putl(s
, ntohl(lsa
->header
->adv_router
));
2217 length
+= sizeof(struct ospf6_lsreq_entry
);
2221 if (last_req
!= NULL
) {
2222 if (on
->last_ls_req
!= NULL
)
2223 on
->last_ls_req
= ospf6_lsa_unlock(on
->last_ls_req
);
2225 ospf6_lsa_lock(last_req
);
2226 on
->last_ls_req
= last_req
;
2232 static uint16_t ospf6_make_lsack_neighbor(struct ospf6_neighbor
*on
,
2233 struct ospf6_packet
**op
)
2235 uint16_t length
= 0;
2236 struct ospf6_lsa
*lsa
, *lsanext
;
2239 for (ALL_LSDB(on
->lsack_list
, lsa
, lsanext
)) {
2240 if ((length
+ sizeof(struct ospf6_lsa_header
)
2241 + OSPF6_HEADER_SIZE
)
2242 > ospf6_packet_max(on
->ospf6_if
)) {
2243 /* if we run out of packet size/space here,
2244 better to try again soon. */
2246 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2247 length
+ OSPF6_HEADER_SIZE
);
2249 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2250 (*op
)->dst
= on
->linklocal_addr
;
2251 ospf6_packet_add(on
->ospf6_if
, *op
);
2252 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2254 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2255 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
,
2256 on
->ospf6_if
, (*op
)->s
);
2261 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2262 stream_put((*op
)->s
, lsa
->header
,
2263 sizeof(struct ospf6_lsa_header
));
2264 length
+= sizeof(struct ospf6_lsa_header
);
2266 assert(lsa
->lock
== 2);
2267 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2273 int ospf6_lsreq_send(struct thread
*thread
)
2275 struct ospf6_neighbor
*on
;
2276 struct ospf6_packet
*op
;
2277 uint16_t length
= OSPF6_HEADER_SIZE
;
2279 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2280 on
->thread_send_lsreq
= (struct thread
*)NULL
;
2282 /* LSReq will be sent only in ExStart or Loading */
2283 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
2284 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
2285 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND_HDR
))
2286 zlog_debug("Quit to send LSReq to neighbor %s state %s",
2288 ospf6_neighbor_state_str
[on
->state
]);
2292 /* schedule loading_done if request list is empty */
2293 if (on
->request_list
->count
== 0) {
2294 thread_add_event(master
, loading_done
, on
, 0, NULL
);
2298 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2299 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSREQ
, on
->ospf6_if
, op
->s
);
2301 length
+= ospf6_make_lsreq(on
, op
->s
);
2303 if (length
== OSPF6_HEADER_SIZE
) {
2304 /* Hello overshooting MTU */
2305 ospf6_packet_free(op
);
2309 /* Fill OSPF header. */
2310 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2312 /* Set packet length */
2313 op
->length
= length
;
2315 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2316 op
->dst
= allspfrouters6
;
2318 op
->dst
= on
->linklocal_addr
;
2320 ospf6_packet_add(on
->ospf6_if
, op
);
2322 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2324 /* set next thread */
2325 if (on
->request_list
->count
!= 0) {
2326 on
->thread_send_lsreq
= NULL
;
2327 thread_add_timer(master
, ospf6_lsreq_send
, on
,
2328 on
->ospf6_if
->rxmt_interval
,
2329 &on
->thread_send_lsreq
);
2335 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
2336 struct ospf6_interface
*oi
,
2337 struct ospf6_packet
*op
)
2342 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2343 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
2344 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
))
2345 op
->dst
= allspfrouters6
;
2347 op
->dst
= on
->linklocal_addr
;
2350 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2351 || (oi
->state
== OSPF6_INTERFACE_DR
)
2352 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2353 op
->dst
= allspfrouters6
;
2355 op
->dst
= alldrouters6
;
2358 ospf6_packet_add(oi
, op
);
2359 OSPF6_MESSAGE_WRITE_ON(oi
);
2363 static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor
*on
,
2364 struct ospf6_packet
**op
, int *lsa_cnt
)
2366 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2367 struct ospf6_lsa
*lsa
, *lsanext
;
2369 /* skip over fixed header */
2370 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2372 for (ALL_LSDB(on
->lsupdate_list
, lsa
, lsanext
)) {
2373 if ((length
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
)
2374 + OSPF6_HEADER_SIZE
)
2375 > ospf6_packet_max(on
->ospf6_if
)) {
2376 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2377 length
+ OSPF6_HEADER_SIZE
);
2378 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2379 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2380 ospf6_send_lsupdate(on
, NULL
, *op
);
2382 /* refresh packet */
2383 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2384 length
= OSPF6_LS_UPD_MIN_SIZE
;
2386 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2387 on
->ospf6_if
, (*op
)->s
);
2388 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2390 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2391 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2393 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2394 assert(lsa
->lock
== 2);
2395 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2400 static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor
*on
,
2401 struct ospf6_packet
**op
,
2404 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2405 struct ospf6_lsa
*lsa
, *lsanext
;
2407 /* skip over fixed header */
2408 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2410 for (ALL_LSDB(on
->retrans_list
, lsa
, lsanext
)) {
2411 if ((length
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
)
2412 + OSPF6_HEADER_SIZE
)
2413 > ospf6_packet_max(on
->ospf6_if
)) {
2414 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2415 length
+ OSPF6_HEADER_SIZE
);
2416 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2417 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2418 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2419 (*op
)->dst
= allspfrouters6
;
2421 (*op
)->dst
= on
->linklocal_addr
;
2423 ospf6_packet_add(on
->ospf6_if
, *op
);
2424 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2426 /* refresh packet */
2427 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2428 length
= OSPF6_LS_UPD_MIN_SIZE
;
2430 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2431 on
->ospf6_if
, (*op
)->s
);
2432 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2434 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2435 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2437 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2442 int ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2444 struct ospf6_neighbor
*on
;
2445 struct ospf6_packet
*op
;
2446 uint16_t length
= OSPF6_HEADER_SIZE
;
2449 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2450 on
->thread_send_lsupdate
= (struct thread
*)NULL
;
2452 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2453 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2455 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2456 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2458 zlog_debug("Quit to send (neighbor state %s)",
2459 ospf6_neighbor_state_str
[on
->state
]);
2463 /* first do lsupdate_list */
2464 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2465 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2466 length
+= ospf6_make_lsupdate_list(on
, &op
, &lsa_cnt
);
2468 /* Fill OSPF header. */
2469 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2470 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2471 op
->length
= length
;
2472 ospf6_send_lsupdate(on
, NULL
, op
);
2474 /* prepare new packet */
2475 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2476 length
= OSPF6_HEADER_SIZE
;
2479 stream_reset(op
->s
);
2480 length
= OSPF6_HEADER_SIZE
;
2483 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2484 /* now do retransmit list */
2485 length
+= ospf6_make_ls_retrans_list(on
, &op
, &lsa_cnt
);
2487 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2488 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2489 op
->length
= length
;
2490 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2491 op
->dst
= allspfrouters6
;
2493 op
->dst
= on
->linklocal_addr
;
2494 ospf6_packet_add(on
->ospf6_if
, op
);
2495 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2497 ospf6_packet_free(op
);
2499 if (on
->lsupdate_list
->count
!= 0) {
2500 on
->thread_send_lsupdate
= NULL
;
2501 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2502 &on
->thread_send_lsupdate
);
2503 } else if (on
->retrans_list
->count
!= 0) {
2504 on
->thread_send_lsupdate
= NULL
;
2505 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2506 on
->ospf6_if
->rxmt_interval
,
2507 &on
->thread_send_lsupdate
);
2512 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2513 struct ospf6_lsa
*lsa
)
2515 struct ospf6_packet
*op
;
2516 uint16_t length
= OSPF6_HEADER_SIZE
;
2518 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2519 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2521 /* skip over fixed header */
2522 stream_forward_endp(op
->s
, OSPF6_LS_UPD_MIN_SIZE
);
2523 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2524 stream_put(op
->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2525 length
= OSPF6_HEADER_SIZE
+ OSPF6_LS_UPD_MIN_SIZE
2526 + OSPF6_LSA_SIZE(lsa
->header
);
2527 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2528 ospf6_fill_lsupdate_header(op
->s
, 1);
2529 op
->length
= length
;
2531 if (IS_OSPF6_DEBUG_FLOODING
2532 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2533 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__
,
2534 lsa
->name
, ntohs(lsa
->header
->age
));
2536 ospf6_send_lsupdate(on
, NULL
, op
);
2541 static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface
*oi
,
2542 struct ospf6_packet
**op
,
2545 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2546 struct ospf6_lsa
*lsa
, *lsanext
;
2548 /* skip over fixed header */
2549 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2551 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
)) {
2552 if (length
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
)
2554 > ospf6_packet_max(oi
)) {
2555 ospf6_fill_header(oi
, (*op
)->s
,
2556 length
+ OSPF6_HEADER_SIZE
);
2557 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2558 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2559 ospf6_send_lsupdate(NULL
, oi
, *op
);
2561 /* refresh packet */
2562 *op
= ospf6_packet_new(oi
->ifmtu
);
2563 length
= OSPF6_LS_UPD_MIN_SIZE
;
2565 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
,
2567 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2570 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2571 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2573 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2575 assert(lsa
->lock
== 2);
2576 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2581 int ospf6_lsupdate_send_interface(struct thread
*thread
)
2583 struct ospf6_interface
*oi
;
2584 struct ospf6_packet
*op
;
2585 uint16_t length
= OSPF6_HEADER_SIZE
;
2588 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2589 oi
->thread_send_lsupdate
= (struct thread
*)NULL
;
2591 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2592 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2595 "Quit to send LSUpdate to interface %s state %s",
2596 oi
->interface
->name
,
2597 ospf6_interface_state_str
[oi
->state
]);
2601 /* if we have nothing to send, return */
2602 if (oi
->lsupdate_list
->count
== 0)
2605 op
= ospf6_packet_new(oi
->ifmtu
);
2606 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
, op
->s
);
2607 length
+= ospf6_make_lsupdate_interface(oi
, &op
, &lsa_cnt
);
2609 /* Fill OSPF header. */
2610 ospf6_fill_header(oi
, op
->s
, length
);
2611 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2612 op
->length
= length
;
2613 ospf6_send_lsupdate(NULL
, oi
, op
);
2615 ospf6_packet_free(op
);
2617 if (oi
->lsupdate_list
->count
> 0) {
2618 oi
->thread_send_lsupdate
= NULL
;
2619 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2620 &oi
->thread_send_lsupdate
);
2626 int ospf6_lsack_send_neighbor(struct thread
*thread
)
2628 struct ospf6_neighbor
*on
;
2629 struct ospf6_packet
*op
;
2630 uint16_t length
= OSPF6_HEADER_SIZE
;
2632 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2633 on
->thread_send_lsack
= (struct thread
*)NULL
;
2635 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2636 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2637 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2639 ospf6_neighbor_state_str
[on
->state
]);
2643 /* if we have nothing to send, return */
2644 if (on
->lsack_list
->count
== 0)
2647 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2648 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, on
->ospf6_if
, op
->s
);
2650 length
+= ospf6_make_lsack_neighbor(on
, &op
);
2652 if (length
== OSPF6_HEADER_SIZE
) {
2653 ospf6_packet_free(op
);
2657 /* Fill OSPF header. */
2658 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2660 /* Set packet length, dst and queue to FIFO. */
2661 op
->length
= length
;
2662 op
->dst
= on
->linklocal_addr
;
2663 ospf6_packet_add(on
->ospf6_if
, op
);
2664 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2666 if (on
->lsack_list
->count
> 0)
2667 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2668 &on
->thread_send_lsack
);
2673 static uint16_t ospf6_make_lsack_interface(struct ospf6_interface
*oi
,
2674 struct ospf6_packet
*op
)
2676 uint16_t length
= 0;
2677 struct ospf6_lsa
*lsa
, *lsanext
;
2679 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
)) {
2680 if ((length
+ sizeof(struct ospf6_lsa_header
)
2681 + OSPF6_HEADER_SIZE
)
2682 > ospf6_packet_max(oi
)) {
2683 /* if we run out of packet size/space here,
2684 better to try again soon. */
2685 THREAD_OFF(oi
->thread_send_lsack
);
2686 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2687 0, &oi
->thread_send_lsack
);
2689 ospf6_lsa_unlock(lsa
);
2691 ospf6_lsa_unlock(lsanext
);
2694 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2695 stream_put(op
->s
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2696 length
+= sizeof(struct ospf6_lsa_header
);
2698 assert(lsa
->lock
== 2);
2699 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2704 int ospf6_lsack_send_interface(struct thread
*thread
)
2706 struct ospf6_interface
*oi
;
2707 struct ospf6_packet
*op
;
2708 uint16_t length
= OSPF6_HEADER_SIZE
;
2710 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2711 oi
->thread_send_lsack
= (struct thread
*)NULL
;
2713 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2714 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2716 "Quit to send LSAck to interface %s state %s",
2717 oi
->interface
->name
,
2718 ospf6_interface_state_str
[oi
->state
]);
2722 /* if we have nothing to send, return */
2723 if (oi
->lsack_list
->count
== 0)
2726 op
= ospf6_packet_new(oi
->ifmtu
);
2727 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, oi
, op
->s
);
2729 length
+= ospf6_make_lsack_interface(oi
, op
);
2731 if (length
== OSPF6_HEADER_SIZE
) {
2732 ospf6_packet_free(op
);
2735 /* Fill OSPF header. */
2736 ospf6_fill_header(oi
, op
->s
, length
);
2738 /* Set packet length, dst and queue to FIFO. */
2739 op
->length
= length
;
2740 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2741 || (oi
->state
== OSPF6_INTERFACE_DR
)
2742 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2743 op
->dst
= allspfrouters6
;
2745 op
->dst
= alldrouters6
;
2747 ospf6_packet_add(oi
, op
);
2748 OSPF6_MESSAGE_WRITE_ON(oi
);
2750 if (oi
->lsack_list
->count
> 0)
2751 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2752 &oi
->thread_send_lsack
);
2758 DEFUN(debug_ospf6_message
, debug_ospf6_message_cmd
,
2759 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2761 "Debug OSPFv3 message\n"
2762 "Debug Unknown message\n"
2763 "Debug Hello message\n"
2764 "Debug Database Description message\n"
2765 "Debug Link State Request message\n"
2766 "Debug Link State Update message\n"
2767 "Debug Link State Acknowledgement message\n"
2768 "Debug All message\n"
2769 "Debug only sending message, entire packet\n"
2770 "Debug only receiving message, entire packet\n"
2771 "Debug only sending message, header only\n"
2772 "Debug only receiving message, header only\n")
2775 int idx_send_recv
= 4;
2776 unsigned char level
= 0;
2781 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2782 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2783 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2784 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2785 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2786 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2787 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2788 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2789 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2790 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2791 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2792 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2793 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2794 type
= OSPF6_MESSAGE_TYPE_ALL
;
2797 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2798 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
2799 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
2800 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2801 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2802 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
2803 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2804 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2805 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2807 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2808 for (i
= 0; i
< 6; i
++)
2809 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
2811 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
2816 DEFUN(no_debug_ospf6_message
, no_debug_ospf6_message_cmd
,
2817 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2818 NO_STR DEBUG_STR OSPF6_STR
2819 "Debug OSPFv3 message\n"
2820 "Debug Unknown message\n"
2821 "Debug Hello message\n"
2822 "Debug Database Description message\n"
2823 "Debug Link State Request message\n"
2824 "Debug Link State Update message\n"
2825 "Debug Link State Acknowledgement message\n"
2826 "Debug All message\n"
2827 "Debug only sending message, entire pkt\n"
2828 "Debug only receiving message, entire pkt\n"
2829 "Debug only sending message, header only\n"
2830 "Debug only receiving message, header only\n")
2833 int idx_send_recv
= 5;
2834 unsigned char level
= 0;
2839 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2840 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2841 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2842 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2843 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2844 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2845 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2846 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2847 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2848 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2849 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2850 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2851 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2852 type
= OSPF6_MESSAGE_TYPE_ALL
;
2855 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
2856 | OSPF6_DEBUG_MESSAGE_SEND_HDR
2857 | OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2858 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
2859 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
2860 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2861 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2862 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
2863 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2864 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2865 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2867 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2868 for (i
= 0; i
< 6; i
++)
2869 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
2871 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
2877 int config_write_ospf6_debug_message(struct vty
*vty
)
2879 const char *type_str
[] = {"unknown", "hello", "dbdesc",
2880 "lsreq", "lsupdate", "lsack"};
2881 unsigned char s
= 0, r
= 0, sh
= 0, rh
= 0;
2884 for (i
= 0; i
< 6; i
++) {
2885 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2887 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2891 for (i
= 0; i
< 6; i
++) {
2892 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2894 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2898 if (s
== 0x3f && r
== 0x3f) {
2899 vty_out(vty
, "debug ospf6 message all\n");
2903 if (s
== 0x3f && r
== 0) {
2904 vty_out(vty
, "debug ospf6 message all send\n");
2906 } else if (s
== 0 && r
== 0x3f) {
2907 vty_out(vty
, "debug ospf6 message all recv\n");
2911 if (sh
== 0x3f && rh
== 0) {
2912 vty_out(vty
, "debug ospf6 message all send-hdr\n");
2914 } else if (sh
== 0 && rh
== 0x3f) {
2915 vty_out(vty
, "debug ospf6 message all recv-hdr\n");
2919 /* Unknown message is logged by default */
2920 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
2921 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2922 vty_out(vty
, "no debug ospf6 message unknown\n");
2923 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
2924 vty_out(vty
, "no debug ospf6 message unknown send\n");
2925 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2926 vty_out(vty
, "no debug ospf6 message unknown recv\n");
2928 for (i
= 1; i
< 6; i
++) {
2929 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
)
2930 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
)) {
2931 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
2935 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2936 vty_out(vty
, "debug ospf6 message %s send\n",
2938 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2939 vty_out(vty
, "debug ospf6 message %s send-hdr\n",
2942 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2943 vty_out(vty
, "debug ospf6 message %s recv\n",
2945 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2946 vty_out(vty
, "debug ospf6 message %s recv-hdr\n",
2953 void install_element_ospf6_debug_message(void)
2955 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
2956 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
2957 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
2958 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);