This change adds a MPTCP netlink command for issuing a REMOVE_ADDR signal for an address over the chosen MPTCP connection from a userspace path manager. The command requires the following parameters: {token, loc_id}.
Unified · Split
| @@ -56,6 +56,7 @@ enum { · 55 unmodified lines | ||
| 56 | 56 | MPTCP_PM_ATTR_RCV_ADD_ADDRS, /* u32 */ |
| 57 | 57 | MPTCP_PM_ATTR_SUBFLOWS, /* u32 */ |
| 58 | 58 | MPTCP_PM_ATTR_TOKEN, /* u32 */ |
| 59 | + MPTCP_PM_ATTR_LOC_ID, /* u8 */ | |
| 59 | 60 | |
| 60 | 61 | __MPTCP_PM_ATTR_MAX |
| 61 | 62 | }; |
| @@ -95,6 +96,7 @@ enum { · 33 unmodified lines | ||
| 95 | 96 | MPTCP_PM_CMD_GET_LIMITS, |
| 96 | 97 | MPTCP_PM_CMD_SET_FLAGS, |
| 97 | 98 | MPTCP_PM_CMD_ANNOUNCE, |
| 99 | + MPTCP_PM_CMD_REMOVE, | |
| 98 | 100 | |
| 99 | 101 | __MPTCP_PM_CMD_AFTER_LAST |
| 100 | 102 | }; |
| @@ -1095,6 +1095,7 @@ static const struct nla_policy mptcp_pm_policy[MPTCP_PM_ATTR_MAX + 1] = { · 1094 unmodified lines | ||
| 1095 | 1095 | [MPTCP_PM_ATTR_RCV_ADD_ADDRS] = { .type = NLA_U32, }, |
| 1096 | 1096 | [MPTCP_PM_ATTR_SUBFLOWS] = { .type = NLA_U32, }, |
| 1097 | 1097 | [MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, }, |
| 1098 | + [MPTCP_PM_ATTR_LOC_ID] = { .type = NLA_U8, }, | |
| 1098 | 1099 | }; |
| 1099 | 1100 | |
| 1100 | 1101 | void mptcp_pm_nl_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk) |
| @@ -1504,8 +1505,8 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info) · 403 unmodified lines | ||
| 1504 | 1505 | return ret; |
| 1505 | 1506 | } |
| 1506 | 1507 | |
| 1507 | −static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, | |
| 1508 | − struct list_head *rm_list) | |
| 1508 | +void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, | |
| 1509 | + struct list_head *rm_list) | |
| 1509 | 1510 | { |
| 1510 | 1511 | struct mptcp_rm_list alist = { .nr = 0 }, slist = { .nr = 0 }; |
| 1511 | 1512 | struct mptcp_pm_addr_entry *entry; |
| @@ -2204,6 +2205,11 @@ static const struct genl_small_ops mptcp_pm_ops[] = { · 692 unmodified lines | ||
| 2204 | 2205 | .doit = mptcp_nl_cmd_announce, |
| 2205 | 2206 | .flags = GENL_ADMIN_PERM, |
| 2206 | 2207 | }, |
| 2208 | + { | |
| 2209 | + .cmd = MPTCP_PM_CMD_REMOVE, | |
| 2210 | + .doit = mptcp_nl_cmd_remove, | |
| 2211 | + .flags = GENL_ADMIN_PERM, | |
| 2212 | + }, | |
| 2207 | 2213 | }; |
| 2208 | 2214 | |
| 2209 | 2215 | static struct genl_family mptcp_genl_family __ro_after_init = { |
| @@ -180,3 +180,65 @@ int mptcp_nl_cmd_announce(struct sk_buff *skb, struct genl_info *info) · 179 unmodified lines | ||
| 180 | 180 | sock_put((struct sock *)msk); |
| 181 | 181 | return err; |
| 182 | 182 | } |
| 183 | + | |
| 184 | +int mptcp_nl_cmd_remove(struct sk_buff *skb, struct genl_info *info) | |
| 185 | +{ | |
| 186 | + struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; | |
| 187 | + struct nlattr *id = info->attrs[MPTCP_PM_ATTR_LOC_ID]; | |
| 188 | + struct mptcp_pm_addr_entry *match = NULL; | |
| 189 | + struct mptcp_pm_addr_entry *entry; | |
| 190 | + struct mptcp_sock *msk; | |
| 191 | + LIST_HEAD(free_list); | |
| 192 | + int err = -EINVAL; | |
| 193 | + u32 token_val; | |
| 194 | + u8 id_val; | |
| 195 | + | |
| 196 | + if (!id || !token) { | |
| 197 | + GENL_SET_ERR_MSG(info, "missing required inputs"); | |
| 198 | + return err; | |
| 199 | + } | |
| 200 | + | |
| 201 | + id_val = nla_get_u8(id); | |
| 202 | + token_val = nla_get_u32(token); | |
| 203 | + | |
| 204 | + msk = mptcp_token_get_sock(sock_net(skb->sk), token_val); | |
| 205 | + if (!msk) { | |
| 206 | + NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); | |
| 207 | + return err; | |
| 208 | + } | |
| 209 | + | |
| 210 | + if (!mptcp_pm_is_userspace(msk)) { | |
| 211 | + GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected"); | |
| 212 | + goto remove_err; | |
| 213 | + } | |
| 214 | + | |
| 215 | + lock_sock((struct sock *)msk); | |
| 216 | + | |
| 217 | + list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { | |
| 218 | + if (entry->addr.id == id_val) { | |
| 219 | + match = entry; | |
| 220 | + break; | |
| 221 | + } | |
| 222 | + } | |
| 223 | + | |
| 224 | + if (!match) { | |
| 225 | + GENL_SET_ERR_MSG(info, "address with specified id not found"); | |
| 226 | + release_sock((struct sock *)msk); | |
| 227 | + goto remove_err; | |
| 228 | + } | |
| 229 | + | |
| 230 | + list_move(&match->list, &free_list); | |
| 231 | + | |
| 232 | + mptcp_pm_remove_addrs_and_subflows(msk, &free_list); | |
| 233 | + | |
| 234 | + release_sock((struct sock *)msk); | |
| 235 | + | |
| 236 | + list_for_each_entry_safe(match, entry, &free_list, list) { | |
| 237 | + sock_kfree_s((struct sock *)msk, match, sizeof(*match)); | |
| 238 | + } | |
| 239 | + | |
| 240 | + err = 0; | |
| 241 | + remove_err: | |
| 242 | + sock_put((struct sock *)msk); | |
| 243 | + return err; | |
| 244 | +} | |
| @@ -801,10 +801,14 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk, · 800 unmodified lines | ||
| 801 | 801 | bool echo); |
| 802 | 802 | int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list); |
| 803 | 803 | int mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list); |
| 804 | +void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, | |
| 805 | + struct list_head *rm_list); | |
| 806 | + | |
| 804 | 807 | int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk, |
| 805 | 808 | struct mptcp_pm_addr_entry *entry); |
| 806 | 809 | void mptcp_free_local_addr_list(struct mptcp_sock *msk); |
| 807 | 810 | int mptcp_nl_cmd_announce(struct sk_buff *skb, struct genl_info *info); |
| 811 | +int mptcp_nl_cmd_remove(struct sk_buff *skb, struct genl_info *info); | |
| 808 | 812 | |
| 809 | 813 | void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk, |
| 810 | 814 | const struct sock *ssk, gfp_t gfp); |