summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonatas Abraitis <donatas@opensourcerouting.org>2022-10-27 07:26:35 +0100
committerGitHub <noreply@github.com>2022-10-27 07:26:35 +0100
commit2ab7bfffde9657d658afbd31f36161b9b453d84a (patch)
treee107e1951b850d678ca045923f82d62fdad90547
parent7d92ea97e216141b28a9a15098929010666ef202 (diff)
parent74fc2957ce09a7128dd036ecd19c38c5f4adf1b9 (diff)
Merge pull request #12206 from FRRouting/mergify/bp/dev/8.4/pr-12179
ospf: optimization for FRR's P2MP mode (backport #12179)
-rw-r--r--ospfd/ospf_flood.c7
-rw-r--r--ospfd/ospf_packet.c3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py156
3 files changed, 164 insertions, 2 deletions
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index e686a93ba9..c2af09a679 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -648,6 +648,13 @@ int ospf_flood_through_interface(struct ospf_interface *oi,
OSPF_SEND_PACKET_DIRECT);
}
} else
+ /* Optimization: for P2MP interfaces,
+ don't send back out the incoming interface immediately,
+ allow time to rx multicast ack to the rx'ed (multicast)
+ update */
+ if (retx_flag != 1 ||
+ oi->type != OSPF_IFTYPE_POINTOMULTIPOINT || inbr == NULL ||
+ oi != inbr->oi)
ospf_ls_upd_send_lsa(oi->nbr_self, lsa,
OSPF_SEND_PACKET_INDIRECT);
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 57643f637e..466b5fa2a2 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -4220,7 +4220,8 @@ static void ospf_ls_ack_send_list(struct ospf_interface *oi, struct list *ack,
op->length = length;
/* Decide destination address. */
- if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
+ oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS);
else
op->dst.s_addr = dst.s_addr;
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py b/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py
index 3b84a99cdf..e131fba0c3 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py
@@ -47,10 +47,12 @@ from lib.common_config import (
step,
create_interfaces_cfg,
topo_daemons,
+ retry,
+ run_frr_cmd,
)
from lib.topolog import logger
from lib.topojson import build_config_from_json
-from lib.topotest import frr_unicode
+from lib.topotest import frr_unicode, json_cmp
from lib.ospf import (
verify_ospf_interface,
@@ -378,6 +380,158 @@ def test_ospf_p2mp_tc1_p0(request):
write_test_footer(tc_name)
+@retry(retry_timeout=30)
+def verify_ospf_json(tgen, dut, input_dict, cmd="show ip ospf database json"):
+ del tgen
+ show_ospf_json = run_frr_cmd(dut, cmd, isjson=True)
+ if not bool(show_ospf_json):
+ return "ospf is not running"
+ result = json_cmp(show_ospf_json, input_dict)
+ return str(result) if result else None
+
+
+@pytest.mark.parametrize("tgen", [2], indirect=True)
+def test_ospf_nbrs(tgen):
+ db_full = {
+ "areas": {
+ "0.0.0.0": {
+ "routerLinkStates": [
+ {
+ "lsId": "100.1.1.0",
+ "advertisedRouter": "100.1.1.0",
+ "numOfRouterLinks": 6,
+ },
+ {
+ "lsId": "100.1.1.1",
+ "advertisedRouter": "100.1.1.1",
+ "numOfRouterLinks": 6,
+ },
+ {
+ "lsId": "100.1.1.2",
+ "advertisedRouter": "100.1.1.2",
+ "numOfRouterLinks": 6,
+ },
+ {
+ "lsId": "100.1.1.3",
+ "advertisedRouter": "100.1.1.3",
+ "numOfRouterLinks": 7,
+ },
+ ]
+ }
+ }
+ }
+ input = [
+ [
+ "r0",
+ "show ip ospf n json",
+ {
+ "neighbors": {
+ "100.1.1.1": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ "100.1.1.2": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ "100.1.1.3": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ }
+ },
+ ],
+ [
+ "r1",
+ "show ip ospf n json",
+ {
+ "neighbors": {
+ "100.1.1.0": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ "100.1.1.2": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ "100.1.1.3": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ }
+ },
+ ],
+ [
+ "r2",
+ "show ip ospf n json",
+ {
+ "neighbors": {
+ "100.1.1.0": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ "100.1.1.1": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ "100.1.1.3": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ }
+ },
+ ],
+ [
+ "r3",
+ "show ip ospf n json",
+ {
+ "neighbors": {
+ "100.1.1.0": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ "100.1.1.1": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ "100.1.1.2": [
+ {
+ "state": "Full/DROther",
+ }
+ ],
+ }
+ },
+ ],
+ ["r0", "show ip ospf database json", db_full],
+ ["r1", "show ip ospf database json", db_full],
+ ["r2", "show ip ospf database json", db_full],
+ ["r3", "show ip ospf database json", db_full],
+ ["r0", "show ip ospf database json", db_full],
+ ["r0", "show ip ospf database router json", {}],
+ ["r0", "show ip ospf interface traffic json", {}],
+ ["r1", "show ip ospf interface traffic json", {}],
+ ["r2", "show ip ospf interface traffic json", {}],
+ ["r3", "show ip ospf interface traffic json", {}],
+ ]
+ for cmd_set in input:
+ step("test_ospf: %s - %s" % (cmd_set[0], cmd_set[1]))
+ assert (
+ verify_ospf_json(tgen, tgen.gears[cmd_set[0]], cmd_set[2], cmd_set[1])
+ is None
+ )
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))