mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
ospfd/ospfclient: add option to flush/withdrawal with zero length
default behavior is unchanged, i.e., to not zero Signed-off-by: Lou Berger <lberger@labn.net>
This commit is contained in:
parent
08172828f6
commit
2f30cb2574
|
@ -482,7 +482,8 @@ int ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient,
|
|||
|
||||
int ospf_apiclient_lsa_delete(struct ospf_apiclient *oclient,
|
||||
struct in_addr addr, uint8_t lsa_type,
|
||||
uint8_t opaque_type, uint32_t opaque_id)
|
||||
uint8_t opaque_type, uint32_t opaque_id,
|
||||
uint8_t flags)
|
||||
{
|
||||
struct msg *msg;
|
||||
int rc;
|
||||
|
@ -497,7 +498,7 @@ 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(), addr, lsa_type,
|
||||
opaque_type, opaque_id);
|
||||
opaque_type, opaque_id, flags);
|
||||
|
||||
rc = ospf_apiclient_send_request(oclient, msg);
|
||||
return rc;
|
||||
|
|
|
@ -95,7 +95,8 @@ int ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient,
|
|||
host byte order */
|
||||
int ospf_apiclient_lsa_delete(struct ospf_apiclient *oclient,
|
||||
struct in_addr addr, uint8_t lsa_type,
|
||||
uint8_t opaque_type, uint32_t opaque_id);
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -534,7 +534,7 @@ struct msg *new_msg_originate_request(uint32_t seqnum, struct in_addr ifaddr,
|
|||
|
||||
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.addr = addr;
|
||||
|
@ -542,6 +542,7 @@ struct msg *new_msg_delete_request(uint32_t seqnum, struct in_addr addr,
|
|||
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));
|
||||
|
|
|
@ -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 addr; /* intf IP for link local, area for type 10, "0.0.0.0" for AS-external */
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -313,7 +321,7 @@ extern struct msg *new_msg_originate_request(uint32_t seqnum,
|
|||
struct lsa_header *data);
|
||||
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);
|
||||
|
|
|
@ -1997,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.
|
||||
*/
|
||||
|
|
|
@ -190,6 +190,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;
|
||||
}
|
||||
|
|
|
@ -124,6 +124,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. */
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue