...so that multiple functions can be subscribed.
The create/destroy hooks are renamed to real/unreal because that's what
they *actually* signal.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
```
r1# sh ipv6 ospf6 summary-address
VRF Name: default
aggregation delay interval :5(in seconds)
```
Just hit this random and looks ugly, let's fix it.
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Moving ospf6_if_p2xp_neighcfg to ospf6_interface.h so we don't need to
include ospf6_neighbor.h.
Signed-off-by: Adriano Marto Reis <adrianomarto@gmail.com>
https://www.rfc-editor.org/rfc/rfc5340.html#page-37 states:
If the interface type is point-
to-multipoint or the interface is in the state Loopback, the
global scope IPv6 addresses associated with the interface (if any)
are copied into the intra-area-prefix-LSA with the PrefixOptions
LA-bit set, the PrefixLength set to 128, and the metric set to 0.
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
When redistributing a local route, ensure the forwarding address field
of AS-External LSAs is only set when the associated nexthop interface
is OSPF-enabled. This is necessary because the OSPF RFC requires that
the AS-External LSA forwarding address should be resolvable using an
intra-area or inter-area path.
Fixes#14462.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Also:
- replace all /* fallthrough */ comments with portable fallthrough;
pseudo keyword to accomodate both gcc and clang
- add missing break; statements as required by older versions of gcc
- cleanup some code to remove unnecessary fallthrough
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
To announce connected prefixes, or not to announce connected prefixes,
that is the question...
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This adds the PtMP interface type, which is effectively identical to PtP
except that all the database flooding & updates are unicast.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Some lower layers still don't handle multicast correctly (or
efficiently.) Add option to send unicast hellos on explicitly
configured neighbors for PtP/PtMP.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
With the configured neighbor list, unicast hellos can be sent. Allow
disabling multicast hellos for that scenario.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This adds a knob to refuse forming adjacencies with neighbors not listed
in the config. Only works on PtP/PtMP of course, otherwise the DR/BDR
machinery gets broken.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Add a list of configured neighbors for each interface. Only stores cost
(and "existence") for now.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
For PtMP the cost may need to be recalculated when the LL addr changes
(since neighbors are configured by LL addr and a different entry with a
different cost may match.)
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Both for virtual links and correct PtMP operation, advertising local
addresses as Intra-Prefix with LA set is a prerequisite. Add the
appropriate entries.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
GCC 13.2.0 complains:
```
ospf6d/ospf6_intra.c:139:25: error: ‘json_arr’ may be used uninitialized [-Werror=maybe-uninitialized]
ospf6d/ospf6_intra.c:485:20: error: ‘json_arr’ may be used uninitialized [-Werror=maybe-uninitialized]
```
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
The newly created LSA `new` is now properly freed to prevent memory leaks when
a non-self-originated Grace LSA which is not in LSDB is received.
The ASan leak log for reference:
```
Direct leak of 400 byte(s) in 2 object(s) allocated from:
#0 0x7f70e984bd28 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded28)
#1 0x7f70e92481c5 in qcalloc lib/memory.c:105
#2 0x55b35068c975 in ospf6_lsa_alloc ospf6d/ospf6_lsa.c:710
#3 0x55b35068c9f9 in ospf6_lsa_create ospf6d/ospf6_lsa.c:725
#4 0x55b35065ab2c in ospf6_receive_lsa ospf6d/ospf6_flood.c:912
#5 0x55b3506a1413 in ospf6_lsupdate_recv ospf6d/ospf6_message.c:1621
#6 0x55b3506a1413 in ospf6_read_helper ospf6d/ospf6_message.c:1896
#7 0x55b3506a1413 in ospf6_receive ospf6d/ospf6_message.c:1925
#8 0x7f70e92e6ccb in event_call lib/event.c:1979
#9 0x7f70e922b488 in frr_run lib/libfrr.c:1213
#10 0x55b35064345e in main ospf6d/ospf6_main.c:250
#11 0x7f70e8843c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
Indirect leak of 72 byte(s) in 2 object(s) allocated from:
#0 0x7f70e984bb40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)
#1 0x7f70e9247ee5 in qmalloc lib/memory.c:100
#2 0x55b35068c987 in ospf6_lsa_alloc ospf6d/ospf6_lsa.c:711
#3 0x55b35068c9f9 in ospf6_lsa_create ospf6d/ospf6_lsa.c:725
#4 0x55b35065ab2c in ospf6_receive_lsa ospf6d/ospf6_flood.c:912
#5 0x55b3506a1413 in ospf6_lsupdate_recv ospf6d/ospf6_message.c:1621
#6 0x55b3506a1413 in ospf6_read_helper ospf6d/ospf6_message.c:1896
#7 0x55b3506a1413 in ospf6_receive ospf6d/ospf6_message.c:1925
#8 0x7f70e92e6ccb in event_call lib/event.c:1979
#9 0x7f70e922b488 in frr_run lib/libfrr.c:1213
#10 0x55b35064345e in main ospf6d/ospf6_main.c:250
#11 0x7f70e8843c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
SUMMARY: AddressSanitizer: 472 byte(s) leaked in 4 allocation(s).
```
Signed-off-by: Keelan Cannoo <keelan.cannoo@icloud.com>
Create a constant OSPFV3_CRYPTO_PROTO_ID to replace the hard-coded
Cryptographic Protocol ID in the OSPFv3 authentication trailer
code. This enhances code clarity and maintainability.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Ensure the OSPFv3 Cryptographic Protocol ID is encoded in network
byte order when appending it to the authentication key. This solves
interoperability issues with other implementations such as BIRD
and IOS-XR.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Include an event ptr-to-ptr in the event_execute() api
call, like the various schedule api calls. This allows the
execute() api to cancel an existing scheduled task if that
task is being executed inline.
Signed-off-by: Mark Stapp <mjs@labn.net>
Make the ospf6_lsa_unlock take the same parameters
that the ospf_lsa_unlock does to make it consistent
and to also ensure that no-one can make the mistake
of getting the pointer cleared up.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
The function ospf6_router_lsa_contains_adj(), ospf6_gr_check_adjs() and ospf6_find_interf_prefix_lsa() iterate through LSDB and lock each LSA. During testing, it was discovered that the lock count did not reach zero upon termination. The stack trace below indicates the leak. To resolve this issue, it was found that unlocking the LSA before returning from the functions solves the problem. This suggests that there was a missing unlock that caused the lock count to remain nonzero.
=================================================================
==22565==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 400 byte(s) in 2 object(s) allocated from:
#0 0x7fa744ccea37 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
#1 0x7fa744867562 in qcalloc ../lib/memory.c:105
#2 0x555cdbb37506 in ospf6_lsa_alloc ../ospf6d/ospf6_lsa.c:710
#3 0x555cdbb375d6 in ospf6_lsa_create ../ospf6d/ospf6_lsa.c:725
#4 0x555cdbaf1008 in ospf6_receive_lsa ../ospf6d/ospf6_flood.c:912
#5 0x555cdbb48ceb in ospf6_lsupdate_recv ../ospf6d/ospf6_message.c:1621
#6 0x555cdbb4ac90 in ospf6_read_helper ../ospf6d/ospf6_message.c:1896
#7 0x555cdbb4aecc in ospf6_receive ../ospf6d/ospf6_message.c:1925
#8 0x7fa744950c33 in event_call ../lib/event.c:1995
#9 0x7fa74483b34a in frr_run ../lib/libfrr.c:1213
#10 0x555cdbacf1eb in main ../ospf6d/ospf6_main.c:250
#11 0x7fa7443f9d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
Objects leaked above:
0x6110000606c0 (200 bytes)
0x611000060940 (200 bytes)
Indirect leak of 80 byte(s) in 2 object(s) allocated from:
#0 0x7fa744cce867 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x7fa744867525 in qmalloc ../lib/memory.c:100
#2 0x555cdbb37520 in ospf6_lsa_alloc ../ospf6d/ospf6_lsa.c:711
#3 0x555cdbb375d6 in ospf6_lsa_create ../ospf6d/ospf6_lsa.c:725
#4 0x555cdbaf1008 in ospf6_receive_lsa ../ospf6d/ospf6_flood.c:912
#5 0x555cdbb48ceb in ospf6_lsupdate_recv ../ospf6d/ospf6_message.c:1621
#6 0x555cdbb4ac90 in ospf6_read_helper ../ospf6d/ospf6_message.c:1896
#7 0x555cdbb4aecc in ospf6_receive ../ospf6d/ospf6_message.c:1925
#8 0x7fa744950c33 in event_call ../lib/event.c:1995
#9 0x7fa74483b34a in frr_run ../lib/libfrr.c:1213
#10 0x555cdbacf1eb in main ../ospf6d/ospf6_main.c:250
#11 0x7fa7443f9d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
Objects leaked above:
0x6040000325d0 (40 bytes)
0x604000032650 (40 bytes)
SUMMARY: AddressSanitizer: 480 byte(s) leaked in 4 allocation(s).
=================================================================
==5483==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 2000 byte(s) in 10 object(s) allocated from:
#0 0x7f2c3faeea37 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
#1 0x7f2c3f68a6d9 in qcalloc ../lib/memory.c:105
#2 0x56431b83633d in ospf6_lsa_alloc ../ospf6d/ospf6_lsa.c:710
#3 0x56431b83640d in ospf6_lsa_create ../ospf6d/ospf6_lsa.c:725
#4 0x56431b7efe13 in ospf6_receive_lsa ../ospf6d/ospf6_flood.c:912
#5 0x56431b847b31 in ospf6_lsupdate_recv ../ospf6d/ospf6_message.c:1621
#6 0x56431b849ad6 in ospf6_read_helper ../ospf6d/ospf6_message.c:1896
#7 0x56431b849d12 in ospf6_receive ../ospf6d/ospf6_message.c:1925
#8 0x7f2c3f773c62 in event_call ../lib/event.c:1995
#9 0x7f2c3f65e2de in frr_run ../lib/libfrr.c:1213
#10 0x56431b7cdff6 in main ../ospf6d/ospf6_main.c:221
#11 0x7f2c3f21dd8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
Objects leaked above:
0x611000060800 (200 bytes)
0x611000060a80 (200 bytes)
0x611000060d00 (200 bytes)
0x611000060f80 (200 bytes)
0x611000061200 (200 bytes)
0x611000061480 (200 bytes)
0x611000061840 (200 bytes)
0x611000061ac0 (200 bytes)
0x61100006c740 (200 bytes)
0x61100006d500 (200 bytes)
Indirect leak of 460 byte(s) in 10 object(s) allocated from:
#0 0x7f2c3faee867 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x7f2c3f68a69c in qmalloc ../lib/memory.c:100
#2 0x56431b836357 in ospf6_lsa_alloc ../ospf6d/ospf6_lsa.c:711
#3 0x56431b83640d in ospf6_lsa_create ../ospf6d/ospf6_lsa.c:725
#4 0x56431b7efe13 in ospf6_receive_lsa ../ospf6d/ospf6_flood.c:912
#5 0x56431b847b31 in ospf6_lsupdate_recv ../ospf6d/ospf6_message.c:1621
#6 0x56431b849ad6 in ospf6_read_helper ../ospf6d/ospf6_message.c:1896
#7 0x56431b849d12 in ospf6_receive ../ospf6d/ospf6_message.c:1925
#8 0x7f2c3f773c62 in event_call ../lib/event.c:1995
#9 0x7f2c3f65e2de in frr_run ../lib/libfrr.c:1213
#10 0x56431b7cdff6 in main ../ospf6d/ospf6_main.c:221
#11 0x7f2c3f21dd8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
Objects leaked above:
0x604000033110 (40 bytes)
0x604000033190 (40 bytes)
0x604000033210 (44 bytes)
0x604000033290 (44 bytes)
0x604000033310 (44 bytes)
0x604000033390 (44 bytes)
0x604000033410 (44 bytes)
0x604000033490 (44 bytes)
0x604000034c90 (44 bytes)
0x6070000d3830 (72 bytes)
SUMMARY: AddressSanitizer: 2460 byte(s) leaked in 20 allocation(s).
Signed-off-by: ryndia <dindyalsarvesh@gmail.com>
The loading_done event needs a event pointer to prevent
use after free's. Testing found this:
ERROR: AddressSanitizer: heap-use-after-free on address 0x613000035130 at pc 0x55ad42d54e5f bp 0x7ffff1e942a0 sp 0x7ffff1e94290
READ of size 1 at 0x613000035130 thread T0
#0 0x55ad42d54e5e in loading_done ospf6d/ospf6_neighbor.c:447
#1 0x55ad42ed7be4 in event_call lib/event.c:1995
#2 0x55ad42e1df75 in frr_run lib/libfrr.c:1213
#3 0x55ad42cf332e in main ospf6d/ospf6_main.c:250
#4 0x7f5798133c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
#5 0x55ad42cf2b19 in _start (/usr/lib/frr/ospf6d+0x248b19)
0x613000035130 is located 48 bytes inside of 384-byte region [0x613000035100,0x613000035280)
freed by thread T0 here:
#0 0x7f57998d77a8 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xde7a8)
#1 0x55ad42e3b4b6 in qfree lib/memory.c:130
#2 0x55ad42d5d049 in ospf6_neighbor_delete ospf6d/ospf6_neighbor.c:180
#3 0x55ad42d1e1ea in interface_down ospf6d/ospf6_interface.c:930
#4 0x55ad42ed7be4 in event_call lib/event.c:1995
#5 0x55ad42ed84fe in _event_execute lib/event.c:2086
#6 0x55ad42d26d7b in ospf6_interface_clear ospf6d/ospf6_interface.c:2847
#7 0x55ad42d73f16 in ospf6_process_reset ospf6d/ospf6_top.c:755
#8 0x55ad42d7e98c in clear_router_ospf6_magic ospf6d/ospf6_top.c:778
#9 0x55ad42d7e98c in clear_router_ospf6 ospf6d/ospf6_top_clippy.c:42
#10 0x55ad42dc2665 in cmd_execute_command_real lib/command.c:994
#11 0x55ad42dc2b32 in cmd_execute_command lib/command.c:1053
#12 0x55ad42dc2fa9 in cmd_execute lib/command.c:1221
#13 0x55ad42ee3cd6 in vty_command lib/vty.c:591
#14 0x55ad42ee4170 in vty_execute lib/vty.c:1354
#15 0x55ad42eec94f in vtysh_read lib/vty.c:2362
#16 0x55ad42ed7be4 in event_call lib/event.c:1995
#17 0x55ad42e1df75 in frr_run lib/libfrr.c:1213
#18 0x55ad42cf332e in main ospf6d/ospf6_main.c:250
#19 0x7f5798133c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
previously allocated by thread T0 here:
#0 0x7f57998d7d28 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded28)
#1 0x55ad42e3ab22 in qcalloc lib/memory.c:105
#2 0x55ad42d5c8ff in ospf6_neighbor_create ospf6d/ospf6_neighbor.c:119
#3 0x55ad42d4c86a in ospf6_hello_recv ospf6d/ospf6_message.c:464
#4 0x55ad42d4c86a in ospf6_read_helper ospf6d/ospf6_message.c:1884
#5 0x55ad42d4c86a in ospf6_receive ospf6d/ospf6_message.c:1925
#6 0x55ad42ed7be4 in event_call lib/event.c:1995
#7 0x55ad42e1df75 in frr_run lib/libfrr.c:1213
#8 0x55ad42cf332e in main ospf6d/ospf6_main.c:250
#9 0x7f5798133c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
Add an actual event pointer and just track it appropriately.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
I'm seeing crashes in ospf6_write on the `assert(node)`. The only
sequence of events that I see that could possibly cause this to happen
is this:
a) Someone has scheduled a outgoing write to the ospf6->t_write and
placed item(s) on the ospf6->oi_write_q
b) A decision is made in ospf6_send_lsupdate() to send an immediate
packet via a event_execute(..., ospf6_write,....).
c) ospf6_write is called and the oi_write_q is cleaned out.
d) the t_write event is now popped and the oi_write_q is empty
and FRR asserts on the `assert(node)` <crash>
When event_execute is called for ospf6_write, just cancel the t_write
event. If ospf6_write has more data to send at the end of the function
it will reschedule itself. I've only seen this crash one time and am
unable to reliably reproduce this at all. But this is the only mechanism
that I can see that could make this happen, given how little the oi_write_q
is actually touched in code.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
When running all daemons with config for most of them, FRR has
sharpd@janelle:~/frr$ vtysh -c "show debug hashtable" | grep "VRF BIT HASH" | wc -l
3570
3570 hashes for bitmaps associated with the vrf. This is a very
large number of hashes. Let's do two things:
a) Reduce the created size of the actually created hashes to 2
instead of 32.
b) Delay generation of the hash *until* a set operation happens.
As that no hash directly implies a unset value if/when checked.
This reduces the number of hashes to 61 in my setup for normal
operation.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
According to RFC 7166, the sequence number should be treated as an
unsigned 64-bit value, although it is stored as two 32-bit values.
When incrementing it, the code caused the lower-order 32-bit value
to skip from 0xFFFFFFFE to 0. As a side effect, an error was never
produced if the full 64-bit sequence number wrapped.
Fixes: #13805
Signed-off-by: David Ward <david.ward@ll.mit.edu>
Commit 76249532fa ("ospf6d: Handle Premature Aging of LSAs") added a
duplicate call to OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(), when the
interface state changes to "Down".
Fixes: #1738
Signed-off-by: David Ward <david.ward@ll.mit.edu>
Change timestamp parameter from int to time_t to avoid truncation.
Found by Coverity Scan (CID 1563226 and 1563222)
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This command makes unplanned GR more reliable by manipulating the
sending of Grace-LSAs and Hello packets for a certain amount of time,
increasing the chance that the neighboring routers are aware of
the ongoing graceful restart before resuming normal OSPF operation.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
In practical terms, unplanned GR refers to the act of recovering
from a software crash without affecting the forwarding plane.
Unplanned GR and Planned GR work virtually the same, except for the
following difference: on planned GR, the router sends the Grace-LSAs
*before* restarting, whereas in unplanned GR the router sends the
Grace-LSAs immediately *after* restarting.
For unplanned GR to work, ospf6d was modified to send a
ZEBRA_CLIENT_GR_CAPABILITIES message to zebra as soon as GR is
enabled. This causes zebra to freeze the OSPF routes in the RIB as
soon as the ospf6d daemon dies, for as long as the configured grace
period (the defaults is 120 seconds). Similarly, ospf6d now stores in
non-volatile memory that GR is enabled as soon as GR is configured.
Those two things are no longer done during the GR preparation phase,
which only happens for planned GRs.
Unplanned GR will only take effect when the daemon is killed
abruptly (e.g. SIGSEGV, SIGKILL), otherwise all OSPF routes will be
uninstalled while ospf6d is exiting. Once ospf6d starts, it will
check whether GR is enabled and enter in the GR mode if necessary,
sending Grace-LSAs out all operational interfaces.
One disadvantage of unplanned GR is that the neighboring routers
might time out their corresponding adjacencies if ospf6d takes too
long to come back up. This is especially the case when short dead
intervals are used (or BFD). For this and other reasons, planned
GR should be preferred whenever possible.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
When ospf6 is started up and SPF is run depending on which route is
selected as the parent route we could miss adding a NH. If one
possible parent route has two equal cost paths and the second possible
parent route has only one depending on which one is selected first
determines if we have have one or two NHs.
In the network below when creating a route 2001:db8:3:4::/64 in R2.
When SPF is run there are two possible parent routes R3 and R4.
2001:db8:1:2 +-----+ 2001:db8:2:5
+--------------+ 2 +---------------+
| ::2 | | ::2 |
| +-----+ |
| |
::1| |
+-----+ |::5
| 1 |2001:db8:1:3+-----+2001:db8:3:5+-----+2001:db8:5:6+-----+
| +------------+ 3 +------------+ 5 +------------+ 6 |
+-----+ ::1 ::3 | |::3 ::5 | |::5 ::6| |
::1| +-----+ +-----+ +-----+
| |::3
| | 2001:db8:3:4
| |
| |::4
| 2001:db8:1:4 +-----+
+--------------+ 4 |
::4 | |
+-----+
The problem was if we first created the route to 2001:db8:3:4::/64 with R3
as the parent route all is fine. The code was merging the NH from the parent
route and R3 has 2 NH, one pointing to R1 and one to R5. But if route
2001:db8:3:4::/64 was first created with parent as R4, it has only one NH
pointing to R1, and then later a new vertex was created pointing to R3 the
code would only copy the nhs from the vertex not from the parent route. The
vertex always has just one NH. But the parent route could have more. So
when we would bringup this setup one time we would see one NH for
2001:db8:3:4::/64 and the next time we would see two NHs. The code has been
modified so that it behaves the same when the route is first created, or when
a vertex is created, it selects the NHs from the parent route.
Signed-off-by: Lynne Morrison <lynne@voltanet.io>