From b51812b183a58d990f02c9ca9552496dedd0b441 Mon Sep 17 00:00:00 2001 From: arbala <bala.arunachalam@iopsys.eu> Date: Tue, 27 May 2025 17:43:50 +0200 Subject: [PATCH] Add vendor extension to reset agents multiap stack --- src/cntlr_commands.c | 12 ++++++++ src/cntlr_commands.h | 13 +++++++++ src/cntlr_commands_impl.c | 38 +++++++++++++++++++++++++ src/cntlr_commands_impl.h | 1 + src/cntlr_extension.c | 59 +++++++++++++++++++++++++++++++++++++++ src/cntlr_extension.h | 7 +++++ src/cntlr_ubus.c | 27 ++++++++++++++++++ 7 files changed, 157 insertions(+) diff --git a/src/cntlr_commands.c b/src/cntlr_commands.c index 97596f80..deaaa015 100644 --- a/src/cntlr_commands.c +++ b/src/cntlr_commands.c @@ -915,6 +915,17 @@ DEFINE_ATTR(disassociate_sta) = { .help = "Reason code for the disassociation.", } }; + +DEFINE_ATTR(reset_agent) = { + [DISASSOCIATE_STA_ATTR_AGENT] = { + .optional = 0, + .pol = { + .name = "agent", + .type = BLOBMSG_TYPE_STRING, + }, + .help = "AL-address of Agent to which the reset_agent CMDU is to be sent", + } +}; #endif DEFINE_ATTR(dump_topology) = { @@ -1008,6 +1019,7 @@ static struct controller_command cntlr_commandlist[] = { #endif #ifdef EASYMESH_VENDOR_EXT CNTLR_CMD(disassociate_sta, "Tell an agent to disassociate a STA."), + CNTLR_CMD(reset_agent, "Reset the multiap stack of an agent."), #endif CNTLR_CMD(dump_topology, "Show tree topology of the Multi-AP network"), CNTLR_CMD(null_command, ""), diff --git a/src/cntlr_commands.h b/src/cntlr_commands.h index 297e7fdb..3f87e281 100644 --- a/src/cntlr_commands.h +++ b/src/cntlr_commands.h @@ -572,6 +572,19 @@ enum disassociate_sta_attrs { DISASSOCIATE_STA_ATTR_REASON, NUM_ATTRS_DISASSOCIATE_STA, }; + +/** + * @enum reset_agent_attrs + * @brief Reset Agent attributes + * + * @ingroup cmdattrs + * @RESET_AGENT_ATTR_AGENT: Agent's AL-address. + * @NUM_ATTRS_RESET_AGENT: Number of reset_agent attributes. + */ +enum reset_agent_attrs { + RESET_AGENT_ATTR_AGENT, + NUM_ATTRS_RESET_AGENT, +}; #endif /** diff --git a/src/cntlr_commands_impl.c b/src/cntlr_commands_impl.c index be560792..6f1f1d2d 100644 --- a/src/cntlr_commands_impl.c +++ b/src/cntlr_commands_impl.c @@ -3319,6 +3319,44 @@ int COMMAND(disassociate_sta)(void *priv, void *args, void *out) return mid != 0xffff ? 0 : -1; } + +int COMMAND(reset_agent)(void *priv, void *args, void *out) +{ + struct controller *c = (struct controller *)priv; + struct blob_buf *bb = (struct blob_buf *)out; + struct blob_attr *tb[NUM_ATTRS_RESET_AGENT]; + struct cmdu_buff *cmdu; + uint8_t agent[6] = {0}; + char agentstr[18] = {0}; + uint16_t mid = 0xffff; + int ret; + + ret = controller_command_parse("reset_agent", args, tb); + if (ret) { + err("%s: Error (ret = %d)\n", __func__, ret); + return -EINVAL; + } + + strncpy(agentstr, blobmsg_data(tb[RESET_AGENT_ATTR_AGENT]), sizeof(agentstr) - 1); + if (!hwaddr_aton(agentstr, agent)) + return -EINVAL; + + cmdu = cntlr_gen_vendor_specific_reset_agent(c); + if (!cmdu) + return -1; + + memcpy(cmdu->origin, agent, 6); + + mid = send_cmdu(c, cmdu); + cmdu_free(cmdu); + + /* reply with mid */ + blobmsg_add_string(bb, "status", mid != 0xffff ? "ok" : "fail"); + if (mid != 0xffff) + blobmsg_add_u32(bb, "mid", mid); + + return mid != 0xffff ? 0 : -1; +} #endif int COMMAND(dump_topology)(void *priv, void *args, void *out) diff --git a/src/cntlr_commands_impl.h b/src/cntlr_commands_impl.h index 84f4dd25..b1ae36eb 100644 --- a/src/cntlr_commands_impl.h +++ b/src/cntlr_commands_impl.h @@ -69,6 +69,7 @@ DECLARE_COMMAND(dpp_advertise_cce); #endif #ifdef EASYMESH_VENDOR_EXT DECLARE_COMMAND(disassociate_sta); +DECLARE_COMMAND(reset_agent); #endif DECLARE_COMMAND(dump_topology); #endif /* CONTROLLER_COMMAND_IMPL_H */ diff --git a/src/cntlr_extension.c b/src/cntlr_extension.c index 1f3304e5..5283156d 100644 --- a/src/cntlr_extension.c +++ b/src/cntlr_extension.c @@ -156,4 +156,63 @@ out: return NULL; } +int cntlr_gen_vendor_specific_reset_agent_tlv(struct controller *c, struct cmdu_buff *frm) +{ + struct tlv *t; + struct tlv_vendor_reset_agent *data; + int ret; + const uint8_t vendor_oui[4] = {0}; + uint32_t oui = 0; + + BUF_PUT_BE24(vendor_oui, EASYMESH_VENDOR_EXT_OUI_DEFAULT); +#ifdef EASYMESH_VENDOR_EXT_OUI + oui = EASYMESH_VENDOR_EXT_OUI; + BUF_PUT_BE24(vendor_oui, oui); +#endif + + /* prepare TLVs */ + t = cmdu_reserve_tlv(frm, 32); + if (!t) { + dbg("%s: -ENOMEM\n", __func__); + return -1; + } + + t->type = TLV_TYPE_VENDOR_SPECIFIC; + t->len = sizeof(struct tlv_vendor_reset_agent); + data = (struct tlv_vendor_reset_agent *)t->data; + + memcpy(data->vendor_impl.vendor.oui, vendor_oui, 3); + data->vendor_impl.vendor_type = TLV_VENDOR_TYPE_IMPL_RESET_AGENT; + + ret = cmdu_put_tlv(frm, t); + if (ret) { + err("%s: error: cmdu_put_tlv()\n", __func__); + return -1; + } + + return 0; +} + +struct cmdu_buff *cntlr_gen_vendor_specific_reset_agent(struct controller *c) +{ + struct cmdu_buff *frm; + int ret; + uint16_t mid = 0; + + frm = cmdu_alloc_simple(CMDU_TYPE_VENDOR_SPECIFIC, &mid); + if (!frm) { + dbg("%s: -ENOMEM\n", __func__); + return NULL; + } + + ret = cntlr_gen_vendor_specific_reset_agent_tlv(c, frm); + if (ret) + goto out; + + cmdu_put_eom(frm); + return frm; +out: + cmdu_free(frm); + return NULL; +} #endif diff --git a/src/cntlr_extension.h b/src/cntlr_extension.h index 17d8de48..00940e5c 100644 --- a/src/cntlr_extension.h +++ b/src/cntlr_extension.h @@ -13,6 +13,7 @@ enum tlv_vendor_type_impl { TLV_VENDOR_TYPE_IMPL_UNSPEC = 0, TLV_VENDOR_TYPE_IMPL_PROBE_REQ = 1, /* Probe Requests */ TLV_VENDOR_TYPE_IMPL_DISASSOCIATE_STA = 2, /* Disassociate STA */ + TLV_VENDOR_TYPE_IMPL_RESET_AGENT = 3, /* Reset agent's MultiAP stack */ }; /* Vendor TLV structure for our implementation */ @@ -34,6 +35,10 @@ struct tlv_vendor_probe_req { uint8_t rcpi; } __attribute__((packed)); +struct tlv_vendor_reset_agent { + struct tlv_vendor_impl vendor_impl; +} __attribute__((packed)); + #ifdef PROPAGATE_PROBE_REQ int handle_vendor_specific_probe_req(void *cntlr, struct cmdu_buff *rx_cmdu, struct tlv_vendor_probe_req *tlv); @@ -42,8 +47,10 @@ int handle_vendor_specific_probe_req(void *cntlr, struct cmdu_buff *rx_cmdu, int handle_vendor_extension(void *cntlr, struct cmdu_buff *rx_cmdu, struct node *n); int cntlr_gen_vendor_specific_disassociate_sta_tlv(struct controller *c, struct cmdu_buff *frm, uint8_t *sta, uint16_t reason); +int cntlr_gen_vendor_specific_reset_agent_tlv(struct controller *c, struct cmdu_buff *frm); struct cmdu_buff *cntlr_gen_vendor_specific_disassociate_sta(struct controller *c, uint8_t *sta, uint16_t reason); +struct cmdu_buff *cntlr_gen_vendor_specific_reset_agent(struct controller *c); #endif #endif /* CNTLR_EXTENSION_H */ diff --git a/src/cntlr_ubus.c b/src/cntlr_ubus.c index d26eeb77..d035e25c 100644 --- a/src/cntlr_ubus.c +++ b/src/cntlr_ubus.c @@ -973,6 +973,32 @@ out: blob_buf_free(&bb); return ret; } + +int cntlr_ubus_reset_agent(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + struct controller *c = container_of(obj, struct controller, obj); + struct blob_buf bb; + int ret; + + memset(&bb, 0, sizeof(bb)); + blob_buf_init(&bb, 0); + + ret = COMMAND(reset_agent)(c, msg, &bb); + if (ret) { + if (ret == -EINVAL) + ret = UBUS_STATUS_INVALID_ARGUMENT; + + goto out; + } + + ubus_send_reply(ctx, req, bb.head); +out: + blob_buf_free(&bb); + return ret; + +} + #endif static int cntlr_ubus_dump_topology(struct ubus_context *ctx, @@ -1129,6 +1155,7 @@ int cntlr_publish_object(struct controller *c, const char *objname) #endif #ifdef EASYMESH_VENDOR_EXT { "disassociate_sta", cntlr_ubus_disassociate_sta }, + { "reset_agent", cntlr_ubus_reset_agent }, #endif #endif { "dump_topology", cntlr_ubus_dump_topology }, -- GitLab