diff options
| -rw-r--r-- | ospfclient/ospf_apiclient.c | 9 | ||||
| -rw-r--r-- | ospfclient/ospf_apiclient.h | 5 | ||||
| -rw-r--r-- | ospfclient/ospfclient.c | 7 | ||||
| -rwxr-xr-x | ospfclient/ospfclient.py | 45 | ||||
| -rw-r--r-- | ospfd/ospf_api.c | 7 | ||||
| -rw-r--r-- | ospfd/ospf_api.h | 17 | ||||
| -rw-r--r-- | ospfd/ospf_apiserver.c | 19 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.c | 1 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.h | 3 | ||||
| -rw-r--r-- | ospfd/ospf_opaque.c | 11 | ||||
| -rw-r--r-- | pimd/pim_nht.c | 5 | ||||
| -rw-r--r-- | pimd/pim_tib.c | 3 | ||||
| -rw-r--r-- | tests/topotests/ospfapi/test_ospf_clientapi.py | 372 |
13 files changed, 379 insertions, 125 deletions
diff --git a/ospfclient/ospf_apiclient.c b/ospfclient/ospf_apiclient.c index b5f5d77d82..4ce65e379a 100644 --- a/ospfclient/ospf_apiclient.c +++ b/ospfclient/ospf_apiclient.c @@ -487,8 +487,9 @@ int ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient, } int ospf_apiclient_lsa_delete(struct ospf_apiclient *oclient, - struct in_addr area_id, uint8_t lsa_type, - uint8_t opaque_type, uint32_t opaque_id) + struct in_addr addr, uint8_t lsa_type, + uint8_t opaque_type, uint32_t opaque_id, + uint8_t flags) { struct msg *msg; int rc; @@ -502,8 +503,8 @@ int ospf_apiclient_lsa_delete(struct ospf_apiclient *oclient, /* opaque_id is in host byte order and will be converted * to network byte order by new_msg_delete_request */ - msg = new_msg_delete_request(ospf_apiclient_get_seqnr(), area_id, - lsa_type, opaque_type, opaque_id); + msg = new_msg_delete_request(ospf_apiclient_get_seqnr(), addr, lsa_type, + opaque_type, opaque_id, flags); rc = ospf_apiclient_send_request(oclient, msg); return rc; diff --git a/ospfclient/ospf_apiclient.h b/ospfclient/ospf_apiclient.h index 6d1eb7f64f..b904937c2a 100644 --- a/ospfclient/ospf_apiclient.h +++ b/ospfclient/ospf_apiclient.h @@ -94,8 +94,9 @@ int ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient, /* Synchronous request to delete opaque LSA. Parameter opaque_id is in host byte order */ int ospf_apiclient_lsa_delete(struct ospf_apiclient *oclient, - struct in_addr area_id, uint8_t lsa_type, - uint8_t opaque_type, uint32_t opaque_id); + struct in_addr addr, uint8_t lsa_type, + uint8_t opaque_type, uint32_t opaque_id, + uint8_t flags); /* Fetch async message and handle it */ int ospf_apiclient_handle_async(struct ospf_apiclient *oclient); diff --git a/ospfclient/ospfclient.c b/ospfclient/ospfclient.c index 3cfee7d573..edf814184a 100644 --- a/ospfclient/ospfclient.c +++ b/ospfclient/ospfclient.c @@ -98,9 +98,10 @@ static void lsa_delete(struct thread *t) printf("Deleting LSA... "); rc = ospf_apiclient_lsa_delete(oclient, area_id, - atoi(args[2]), /* lsa type */ - atoi(args[3]), /* opaque type */ - atoi(args[4])); /* opaque ID */ + atoi(args[2]), /* lsa type */ + atoi(args[3]), /* opaque type */ + atoi(args[4]), /* opaque ID */ + 0); /* send data in withdrawals */ printf("done, return code is = %d\n", rc); } diff --git a/ospfclient/ospfclient.py b/ospfclient/ospfclient.py index 19561145a0..8e3c68445f 100755 --- a/ospfclient/ospfclient.py +++ b/ospfclient/ospfclient.py @@ -62,13 +62,16 @@ smsg_info = { MSG_REGISTER_EVENT: ("REGISTER_EVENT", FMT_LSA_FILTER), MSG_SYNC_LSDB: ("SYNC_LSDB", FMT_LSA_FILTER), MSG_ORIGINATE_REQUEST: ("ORIGINATE_REQUEST", ">II" + FMT_LSA_HEADER[1:]), - MSG_DELETE_REQUEST: ("DELETE_REQUEST", ">IBBxxL"), + MSG_DELETE_REQUEST: ("DELETE_REQUEST", ">IBBxBL"), MSG_SYNC_REACHABLE: ("MSG_SYNC_REACHABLE", ""), MSG_SYNC_ISM: ("MSG_SYNC_ISM", ""), MSG_SYNC_NSM: ("MSG_SYNC_NSM", ""), MSG_SYNC_ROUTER_ID: ("MSG_SYNC_ROUTER_ID", ""), } +# OSPF API MSG Delete Flag. +OSPF_API_DEL_ZERO_LEN_LSA = 0x01 # send withdrawal with no LSA data + # -------------------------- # Messages from OSPF daemon. # -------------------------- @@ -842,7 +845,7 @@ class OspfOpaqueClient(OspfApiClient): await self._assure_opaque_ready(lsa_type, otype) await self.msg_send_raises(mt, msg) - async def delete_opaque_data(self, addr, lsa_type, otype, oid): + async def delete_opaque_data(self, addr, lsa_type, otype, oid, flags=0): """Delete an instance of opaque data. Delete an instance of opaque data. This call will register for the given @@ -854,6 +857,7 @@ class OspfOpaqueClient(OspfApiClient): otype: (octet) opaque type. Note: the type will be registered if the user has not explicity done that yet with `register_opaque_data`. oid: (3 octets) ID of this opaque data + flags: (octet) optional flags (e.g., OSPF_API_DEL_ZERO_LEN_LSA, defaults to no flags) Raises: See `msg_send_raises` """ @@ -862,7 +866,7 @@ class OspfOpaqueClient(OspfApiClient): mt = MSG_DELETE_REQUEST await self._assure_opaque_ready(lsa_type, otype) - mp = struct.pack(msg_fmt[mt], int(addr), lsa_type, otype, oid) + mp = struct.pack(msg_fmt[mt], int(addr), lsa_type, otype, flags, oid) await self.msg_send_raises(mt, mp) async def register_opaque_data(self, lsa_type, otype, callback=None): @@ -1115,23 +1119,28 @@ async def async_main(args): except ValueError: addr = ip(aval) oargs = [addr, ltype, int(_s.pop(False)), int(_s.pop(False))] - assert len(_s) <= 1, "Bad format for action argument" - try: - b = bytes.fromhex(_s.pop(False)) - except IndexError: - b = b"" - logging.info("opaque data is %s octets", len(b)) - # Needs to be multiple of 4 in length - mod = len(b) % 4 - if mod: - b += b"\x00" * (4 - mod) - logging.info("opaque padding to %s octets", len(b)) - if what.casefold() == "add": + try: + b = bytes.fromhex(_s.pop(False)) + except IndexError: + b = b"" + logging.info("opaque data is %s octets", len(b)) + # Needs to be multiple of 4 in length + mod = len(b) % 4 + if mod: + b += b"\x00" * (4 - mod) + logging.info("opaque padding to %s octets", len(b)) + await c.add_opaque_data(*oargs, b) else: assert what.casefold().startswith("del") - await c.delete_opaque_data(*oargs) + f = 0 + if len(_s) >= 1: + try: + f = int(_s.pop(False)) + except IndexError: + f = 0 + await c.delete_opaque_data(*oargs, f) if args.exit: return 0 except Exception as error: @@ -1153,7 +1162,9 @@ def main(*args): ap.add_argument("--server", default="localhost", help="OSPF API server") ap.add_argument("-v", "--verbose", action="store_true", help="be verbose") ap.add_argument( - "actions", nargs="*", help="(ADD|DEL),LSATYPE,[ADDR,],OTYPE,OID,[HEXDATA]" + "actions", + nargs="*", + help="(ADD|DEL),LSATYPE,[ADDR,],OTYPE,OID,[HEXDATA|DEL_FLAG]", ) args = ap.parse_args() diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c index 8636db450b..9a134d033c 100644 --- a/ospfd/ospf_api.c +++ b/ospfd/ospf_api.c @@ -532,16 +532,17 @@ struct msg *new_msg_originate_request(uint32_t seqnum, struct in_addr ifaddr, return msg_new(MSG_ORIGINATE_REQUEST, omsg, seqnum, omsglen); } -struct msg *new_msg_delete_request(uint32_t seqnum, struct in_addr area_id, +struct msg *new_msg_delete_request(uint32_t seqnum, struct in_addr addr, uint8_t lsa_type, uint8_t opaque_type, - uint32_t opaque_id) + uint32_t opaque_id, uint8_t flags) { struct msg_delete_request dmsg; - dmsg.area_id = area_id; + dmsg.addr = addr; dmsg.lsa_type = lsa_type; dmsg.opaque_type = opaque_type; dmsg.opaque_id = htonl(opaque_id); memset(&dmsg.pad, 0, sizeof(dmsg.pad)); + dmsg.flags = flags; return msg_new(MSG_DELETE_REQUEST, &dmsg, seqnum, sizeof(struct msg_delete_request)); diff --git a/ospfd/ospf_api.h b/ospfd/ospf_api.h index 51c8c52ce5..6f569e962d 100644 --- a/ospfd/ospf_api.h +++ b/ospfd/ospf_api.h @@ -185,11 +185,19 @@ struct msg_originate_request { struct lsa_header data; }; + +/* OSPF API MSG Delete Flag. */ +#define OSPF_API_DEL_ZERO_LEN_LSA 0x01 /* send withdrawal with no LSA data */ + +#define IS_DEL_ZERO_LEN_LSA(x) ((x)->flags & OSPF_API_DEL_ZERO_LEN_LSA) + struct msg_delete_request { - struct in_addr area_id; /* "0.0.0.0" for AS-external opaque LSAs */ + struct in_addr addr; /* intf IP for link local, area for type 10, + "0.0.0.0" for AS-external */ uint8_t lsa_type; uint8_t opaque_type; - uint8_t pad[2]; /* padding */ + uint8_t pad; /* padding */ + uint8_t flags; /* delete flags */ uint32_t opaque_id; }; @@ -311,10 +319,9 @@ extern struct msg *new_msg_originate_request(uint32_t seqnum, struct in_addr ifaddr, struct in_addr area_id, struct lsa_header *data); -extern struct msg *new_msg_delete_request(uint32_t seqnum, - struct in_addr area_id, +extern struct msg *new_msg_delete_request(uint32_t seqnum, struct in_addr addr, uint8_t lsa_type, uint8_t opaque_type, - uint32_t opaque_id); + uint32_t opaque_id, uint8_t flags); /* Messages sent by OSPF daemon */ extern struct msg *new_msg_reply(uint32_t seqnum, uint8_t rc); diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index f5ed77dab5..0c2ee0c4f8 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -1924,6 +1924,7 @@ int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv, struct msg_delete_request *dmsg; struct ospf_lsa *old; struct ospf_area *area = NULL; + struct ospf_interface *oi = NULL; struct in_addr id; int lsa_type, opaque_type; int rc = 0; @@ -1938,11 +1939,20 @@ int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv, /* Lookup area for link-local and area-local opaque LSAs */ switch (dmsg->lsa_type) { case OSPF_OPAQUE_LINK_LSA: + oi = ospf_apiserver_if_lookup_by_addr(dmsg->addr); + if (!oi) { + zlog_warn("%s: unknown interface %pI4", __func__, + &dmsg->addr); + rc = OSPF_API_NOSUCHINTERFACE; + goto out; + } + area = oi->area; + break; case OSPF_OPAQUE_AREA_LSA: - area = ospf_area_lookup_by_area_id(ospf, dmsg->area_id); + area = ospf_area_lookup_by_area_id(ospf, dmsg->addr); if (!area) { zlog_warn("%s: unknown area %pI4", __func__, - &dmsg->area_id); + &dmsg->addr); rc = OSPF_API_NOSUCHAREA; goto out; } @@ -1987,6 +1997,11 @@ int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv, goto out; } + if (IS_DEL_ZERO_LEN_LSA(dmsg)) { + /* minimize the size of the withdrawal: */ + old->opaque_zero_len_delete = 1; + } + /* Schedule flushing of LSA from LSDB */ /* NB: Multiple scheduling will produce a warning message, but harmless. */ diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 0df0072f6d..365f373d2f 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -188,6 +188,7 @@ struct ospf_lsa *ospf_lsa_new(void) new->refresh_list = -1; new->vrf_id = VRF_DEFAULT; new->to_be_acknowledged = 0; + new->opaque_zero_len_delete = 0; return new; } diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 97c15d1e3c..1caf8047e4 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -123,6 +123,9 @@ struct ospf_lsa { /*For topo chg detection in HELPER role*/ bool to_be_acknowledged; + + /* send maxage with no data */ + bool opaque_zero_len_delete; }; /* OSPF LSA Link Type. */ diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 261d69df33..ab647625fe 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -2050,6 +2050,17 @@ void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0) goto out; } + if (lsa->opaque_zero_len_delete && + lsa->data->length != htons(sizeof(struct lsa_header))) { + /* minimize the size of the withdrawal: */ + /* increment the sequence number and make len just header */ + /* and update checksum */ + lsa->data->ls_seqnum = lsa_seqnum_increment(lsa); + lsa->data->length = htons(sizeof(struct lsa_header)); + lsa->data->checksum = 0; + lsa->data->checksum = ospf_lsa_checksum(lsa->data); + } + /* Delete this lsa from neighbor retransmit-list. */ switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 9feb064e96..f9a9aeb1b0 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -495,12 +495,13 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim, uint32_t hash_val = 0, mod_val = 0; uint8_t nh_iter = 0, found = 0; uint32_t i, num_nbrs = 0; - pim_addr nh_addr = nexthop->mrib_nexthop_addr; - pim_addr grp_addr = pim_addr_from_prefix(grp); if (!pnc || !pnc->nexthop_num || !nexthop) return 0; + pim_addr nh_addr = nexthop->mrib_nexthop_addr; + pim_addr grp_addr = pim_addr_from_prefix(grp); + memset(&nbrs, 0, sizeof(nbrs)); memset(&ifps, 0, sizeof(ifps)); diff --git a/pimd/pim_tib.c b/pimd/pim_tib.c index 8f5de3e938..3455e30064 100644 --- a/pimd/pim_tib.c +++ b/pimd/pim_tib.c @@ -49,7 +49,8 @@ tib_sg_oil_setup(struct pim_instance *pim, pim_sgaddr sg, struct interface *oif) if (up) { memcpy(&nexthop, &up->rpf.source_nexthop, sizeof(struct pim_nexthop)); - pim_ecmp_nexthop_lookup(pim, &nexthop, vif_source, &grp, 0); + (void)pim_ecmp_nexthop_lookup(pim, &nexthop, vif_source, &grp, + 0); if (nexthop.interface) input_iface_vif_index = pim_if_find_vifindex_by_ifindex( pim, nexthop.interface->ifindex); diff --git a/tests/topotests/ospfapi/test_ospf_clientapi.py b/tests/topotests/ospfapi/test_ospf_clientapi.py index f6928d7cd0..94c8c5c732 100644 --- a/tests/topotests/ospfapi/test_ospf_clientapi.py +++ b/tests/topotests/ospfapi/test_ospf_clientapi.py @@ -472,52 +472,70 @@ def _test_opaque_add_del(tgen, apibin): [ apibin, "-v", + "add,9,10.0.1.1,230,1", "add,9,10.0.1.1,230,2,00000202", - "add,10,1.2.3.4,231,1,00010101", "wait,1", - "add,10,1.2.3.4,231,2", - "add,11,232,3,ebadf00d", + "add,10,1.2.3.4,231,1", + "add,10,1.2.3.4,231,2,0102030405060708", + "wait,1", + "add,11,232,1", + "add,11,232,2,ebadf00d", "wait,20", - "del,10,1.2.3.4,231,1", - "del,10,1.2.3.4,231,2", + "del,9,10.0.1.1,230,2,0", + "del,10,1.2.3.4,231,2,1", + "del,11,232,1,1", ] ) - add_input_dict = { "areas": { "1.2.3.4": { "linkLocalOpaqueLsa": [ { + "lsId": "230.0.0.1", + "advertisedRouter": "192.168.0.1", + "sequenceNumber": "80000001", + "checksum": "6d5f", + }, + { "lsId": "230.0.0.2", "advertisedRouter": "192.168.0.1", "sequenceNumber": "80000001", "checksum": "8142", - } + }, ], + "linkLocalOpaqueLsaCount": 2, "areaLocalOpaqueLsa": [ { "lsId": "231.0.0.1", "advertisedRouter": "192.168.0.1", "sequenceNumber": "80000001", - "checksum": "695a", + "checksum": "5278", }, { "lsId": "231.0.0.2", "advertisedRouter": "192.168.0.1", "sequenceNumber": "80000001", - "checksum": "4881", + "checksum": "6d30", }, ], - } + "areaLocalOpaqueLsaCount": 2, + }, }, "asExternalOpaqueLsa": [ { - "lsId": "232.0.0.3", + "lsId": "232.0.0.1", "advertisedRouter": "192.168.0.1", "sequenceNumber": "80000001", - "checksum": "c666", - } + "checksum": "5575", + }, + { + "lsId": "232.0.0.2", + "advertisedRouter": "192.168.0.1", + "sequenceNumber": "80000001", + "checksum": "d05d", + }, ], + "asExternalOpaqueLsaCount": 2, } step("reachable: check for add LSAs") @@ -537,6 +555,14 @@ def _test_opaque_add_del(tgen, apibin): "areas": { "1.2.3.4": [ { + "linkStateId": "230.0.0.1", + "advertisingRouter": "192.168.0.1", + "lsaSeqNumber": "80000001", + "checksum": "6d5f", + "length": 20, + "opaqueDataLength": 0, + }, + { "linkStateId": "230.0.0.2", "advertisingRouter": "192.168.0.1", "lsaSeqNumber": "80000001", @@ -544,7 +570,7 @@ def _test_opaque_add_del(tgen, apibin): "length": 24, "opaqueId": 2, "opaqueDataLength": 4, - } + }, ] } } @@ -557,33 +583,41 @@ def _test_opaque_add_del(tgen, apibin): "linkStateId": "231.0.0.1", "advertisingRouter": "192.168.0.1", "lsaSeqNumber": "80000001", - "checksum": "695a", - "length": 24, - "opaqueDataLength": 4, + "checksum": "5278", + "length": 20, + "opaqueDataLength": 0, }, { "linkStateId": "231.0.0.2", "advertisingRouter": "192.168.0.1", "lsaSeqNumber": "80000001", - "checksum": "4881", - "length": 20, - "opaqueDataLength": 0, + "checksum": "6d30", + "length": 28, + "opaqueDataLength": 8, }, - ] - } - } + ], + }, + }, }, { "asExternalOpaqueLsa": [ { - "linkStateId": "232.0.0.3", + "linkStateId": "232.0.0.1", + "advertisingRouter": "192.168.0.1", + "lsaSeqNumber": "80000001", + "checksum": "5575", + "length": 20, + "opaqueDataLength": 0, + }, + { + "linkStateId": "232.0.0.2", "advertisingRouter": "192.168.0.1", "lsaSeqNumber": "80000001", - "checksum": "c666", + "checksum": "d05d", "length": 24, "opaqueDataLength": 4, - } - ] + }, + ], }, ] i = 0 @@ -602,9 +636,16 @@ def _test_opaque_add_del(tgen, apibin): # Wait for add notification # RECV: LSA update msg for LSA 232.0.0.3 in area 0.0.0.0 seq 0x80000001 len 24 age 9 - step("reachable: check for API add notifications") - ls_ids = ["230.0.0.2", "231.0.0.1", "231.0.0.2", "232.0.0.3"] + ls_ids = [ + "230.0.0.1", + "230.0.0.2", + "231.0.0.1", + "231.0.0.2", + "232.0.0.1", + "232.0.0.2", + ] for ls_id in ls_ids: + step("reachable: check for API add notification: %s" % ls_id) waitfor = "RECV:.*update msg.*LSA {}.*age ([0-9]+)".format(ls_id) _ = _wait_output(pread, waitfor) @@ -613,38 +654,54 @@ def _test_opaque_add_del(tgen, apibin): "1.2.3.4": { "linkLocalOpaqueLsa": [ { + "lsId": "230.0.0.1", + "advertisedRouter": "192.168.0.1", + "sequenceNumber": "80000001", + "checksum": "6d5f", + }, + { "lsId": "230.0.0.2", "advertisedRouter": "192.168.0.1", + "lsaAge": 3600, "sequenceNumber": "80000001", "checksum": "8142", - } + }, ], + "linkLocalOpaqueLsaCount": 2, "areaLocalOpaqueLsa": [ { - "lsaAge": 3600, "lsId": "231.0.0.1", "advertisedRouter": "192.168.0.1", "sequenceNumber": "80000001", - "checksum": "695a", + "checksum": "5278", }, { - "lsaAge": 3600, "lsId": "231.0.0.2", "advertisedRouter": "192.168.0.1", - "sequenceNumber": "80000001", - "checksum": "4881", + "lsaAge": 3600, + "sequenceNumber": "80000002", + "checksum": "4682", }, ], - } + "areaLocalOpaqueLsaCount": 2, + }, }, "asExternalOpaqueLsa": [ { - "lsId": "232.0.0.3", + "lsId": "232.0.0.1", "advertisedRouter": "192.168.0.1", + "lsaAge": 3600, "sequenceNumber": "80000001", - "checksum": "c666", - } + "checksum": "5575", + }, + { + "lsId": "232.0.0.2", + "advertisedRouter": "192.168.0.1", + "sequenceNumber": "80000001", + "checksum": "d05d", + }, ], + "asExternalOpaqueLsaCount": 2, } step("reachable: check for explicit withdrawal LSAs") @@ -652,64 +709,207 @@ def _test_opaque_add_del(tgen, apibin): assert verify_ospf_database(tgen, r1, del_input_dict, json_cmd) is None assert verify_ospf_database(tgen, r2, del_input_dict, json_cmd) is None + del_detail_input_dict = [ + { + "linkLocalOpaqueLsa": { + "areas": { + "1.2.3.4": [ + { + "linkStateId": "230.0.0.1", + "advertisingRouter": "192.168.0.1", + "lsaSeqNumber": "80000001", + "checksum": "6d5f", + "length": 20, + "opaqueDataLength": 0, + }, + { + "linkStateId": "230.0.0.2", + "advertisingRouter": "192.168.0.1", + "lsaAge": 3600, + "lsaSeqNumber": "80000001", + "checksum": "8142", + "length": 24, + "opaqueId": 2, + "opaqueDataLength": 4, + }, + ] + } + } + }, + { + "areaLocalOpaqueLsa": { + "areas": { + "1.2.3.4": [ + { + "linkStateId": "231.0.0.1", + "advertisingRouter": "192.168.0.1", + "lsaSeqNumber": "80000001", + "checksum": "5278", + "length": 20, + "opaqueDataLength": 0, + }, + { + "lsaAge": 3600, + "linkStateId": "231.0.0.2", + "advertisingRouter": "192.168.0.1", + "lsaSeqNumber": "80000002", + "checksum": "4682", + # data removed + "length": 20, + "opaqueDataLength": 0, + }, + ], + }, + }, + }, + { + "asExternalOpaqueLsa": [ + { + "linkStateId": "232.0.0.1", + "advertisingRouter": "192.168.0.1", + "lsaAge": 3600, + "lsaSeqNumber": "80000001", + "checksum": "5575", + "length": 20, + "opaqueDataLength": 0, + }, + { + "linkStateId": "232.0.0.2", + "advertisingRouter": "192.168.0.1", + "lsaSeqNumber": "80000001", + "checksum": "d05d", + "length": 24, + "opaqueDataLength": 4, + }, + ], + }, + ] + i = 0 + while i < numcs: + step("reachable: check for delete LSA details: %s" % json_cmds[i]) + assert ( + verify_ospf_database(tgen, r1, del_detail_input_dict[i], json_cmds[i]) + is None + ) + assert ( + verify_ospf_database(tgen, r2, del_detail_input_dict[i], json_cmds[i]) + is None + ) + i += 1 + p.terminate() if p.wait(): comm_error(p) - del_input_dict = { - "areas": { - "1.2.3.4": { - "linkLocalOpaqueLsa": [ - { - "lsaAge": 3600, - "lsId": "230.0.0.2", - "advertisedRouter": "192.168.0.1", - "sequenceNumber": "80000001", - "checksum": "8142", - } - ], - "areaLocalOpaqueLsa": [ - { - "lsaAge": 3600, - "lsId": "231.0.0.1", - "advertisedRouter": "192.168.0.1", - "sequenceNumber": "80000001", - "checksum": "695a", - }, - { - "lsaAge": 3600, - "lsId": "231.0.0.2", - "advertisedRouter": "192.168.0.1", - "sequenceNumber": "80000001", - "checksum": "4881", - }, - ], + + del_detail_input_dict = [ + { + "linkLocalOpaqueLsa": { + "areas": { + "1.2.3.4": [ + { + "linkStateId": "230.0.0.1", + "advertisingRouter": "192.168.0.1", + "lsaAge": 3600, + "lsaSeqNumber": "80000001", + "checksum": "6d5f", + "length": 20, + "opaqueDataLength": 0, + }, + { + "linkStateId": "230.0.0.2", + "advertisingRouter": "192.168.0.1", + "lsaAge": 3600, + "lsaSeqNumber": "80000001", + "checksum": "8142", + "length": 24, + "opaqueId": 2, + "opaqueDataLength": 4, + }, + ] + } } }, - "asExternalOpaqueLsa": [ - { - "lsaAge": 3600, - "lsId": "232.0.0.3", - "advertisedRouter": "192.168.0.1", - "sequenceNumber": "80000001", - "checksum": "c666", - } - ], - } - - step("reachable: check for implicit withdrawal LSAs") - json_cmd = "show ip ospf da json" - assert verify_ospf_database(tgen, r1, del_input_dict, json_cmd) is None - assert verify_ospf_database(tgen, r2, del_input_dict, json_cmd) is None + { + "areaLocalOpaqueLsa": { + "areas": { + "1.2.3.4": [ + { + "lsaAge": 3600, + "linkStateId": "231.0.0.1", + "advertisingRouter": "192.168.0.1", + "lsaSeqNumber": "80000001", + "checksum": "5278", + "length": 20, + "opaqueDataLength": 0, + }, + { + "lsaAge": 3600, + "linkStateId": "231.0.0.2", + "advertisingRouter": "192.168.0.1", + "lsaSeqNumber": "80000002", + "checksum": "4682", + # data removed + "length": 20, + "opaqueDataLength": 0, + }, + ], + }, + }, + }, + { + "asExternalOpaqueLsa": [ + { + "linkStateId": "232.0.0.1", + "advertisingRouter": "192.168.0.1", + "lsaAge": 3600, + "lsaSeqNumber": "80000001", + "checksum": "5575", + "length": 20, + "opaqueDataLength": 0, + }, + { + "linkStateId": "232.0.0.2", + "advertisingRouter": "192.168.0.1", + "lsaAge": 3600, + "lsaSeqNumber": "80000001", + "checksum": "d05d", + "length": 24, + "opaqueDataLength": 4, + }, + ], + }, + ] + i = 0 + while i < numcs: + step( + "reachable: check for post API shutdown delete LSA details: %s" + % json_cmds[i] + ) + assert ( + verify_ospf_database(tgen, r1, del_detail_input_dict[i], json_cmds[i]) + is None + ) + assert ( + verify_ospf_database(tgen, r2, del_detail_input_dict[i], json_cmds[i]) + is None + ) + i += 1 # step("reachable: check for flush/age out") # # Wait for max age notification # waitfor = "RECV:.*update msg.*LSA {}.*age 3600".format(ls_id) # _wait_output(pread, waitfor) - - step("reachable: check for API delete notifications") - ls_ids = ["231.0.0.1", "231.0.0.2", "230.0.0.2", "232.0.0.3"] + ls_ids = [ + "230.0.0.2", + "231.0.0.2", + "232.0.0.1", + "230.0.0.1", + "231.0.0.1", + "232.0.0.2", + ] for ls_id in ls_ids: - waitfor = "RECV:.*delete msg.*LSA {}.*".format(ls_id) + step("reachable: check for API delete notification: %s" % ls_id) + waitfor = "RECV:.*delete msg.*LSA {}.*age".format(ls_id) _ = _wait_output(pread, waitfor) except Exception: if p: |
