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 | MPTCP_PM_ATTR_RCV_ADD_ADDRS, /* u32 */ | 56 | MPTCP_PM_ATTR_RCV_ADD_ADDRS, /* u32 */ |
| 57 | MPTCP_PM_ATTR_SUBFLOWS, /* u32 */ | 57 | MPTCP_PM_ATTR_SUBFLOWS, /* u32 */ |
| 58 | MPTCP_PM_ATTR_TOKEN, /* u32 */ | 58 | MPTCP_PM_ATTR_TOKEN, /* u32 */ |
| 59 | MPTCP_PM_ATTR_LOC_ID, /* u8 */ | ||
| 59 | 60 | ||
| 60 | __MPTCP_PM_ATTR_MAX | 61 | __MPTCP_PM_ATTR_MAX |
| 61 | }; | 62 | }; |
| @@ -95,6 +96,7 @@ enum { · 33 unmodified lines | |||
| 95 | MPTCP_PM_CMD_GET_LIMITS, | 96 | MPTCP_PM_CMD_GET_LIMITS, |
| 96 | MPTCP_PM_CMD_SET_FLAGS, | 97 | MPTCP_PM_CMD_SET_FLAGS, |
| 97 | MPTCP_PM_CMD_ANNOUNCE, | 98 | MPTCP_PM_CMD_ANNOUNCE, |
| 99 | MPTCP_PM_CMD_REMOVE, | ||
| 98 | 100 | ||
| 99 | __MPTCP_PM_CMD_AFTER_LAST | 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 | [MPTCP_PM_ATTR_RCV_ADD_ADDRS] = { .type = NLA_U32, }, | 1095 | [MPTCP_PM_ATTR_RCV_ADD_ADDRS] = { .type = NLA_U32, }, |
| 1096 | [MPTCP_PM_ATTR_SUBFLOWS] = { .type = NLA_U32, }, | 1096 | [MPTCP_PM_ATTR_SUBFLOWS] = { .type = NLA_U32, }, |
| 1097 | [MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, }, | 1097 | [MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, }, |
| 1098 | [MPTCP_PM_ATTR_LOC_ID] = { .type = NLA_U8, }, | ||
| 1098 | }; | 1099 | }; |
| 1099 | 1100 | ||
| 1100 | void mptcp_pm_nl_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk) | 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 | return ret; | 1505 | return ret; |
| 1505 | } | 1506 | } |
| 1506 | 1507 | ||
| 1507 | static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, | 1508 | void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, |
| 1508 | struct list_head *rm_list) | 1509 | struct list_head *rm_list) |
| 1509 | { | 1510 | { |
| 1510 | struct mptcp_rm_list alist = { .nr = 0 }, slist = { .nr = 0 }; | 1511 | struct mptcp_rm_list alist = { .nr = 0 }, slist = { .nr = 0 }; |
| 1511 | struct mptcp_pm_addr_entry *entry; | 1512 | struct mptcp_pm_addr_entry *entry; |
| @@ -2204,6 +2205,11 @@ static const struct genl_small_ops mptcp_pm_ops[] = { · 692 unmodified lines | |||
| 2204 | .doit = mptcp_nl_cmd_announce, | 2205 | .doit = mptcp_nl_cmd_announce, |
| 2205 | .flags = GENL_ADMIN_PERM, | 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 | static struct genl_family mptcp_genl_family __ro_after_init = { | 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 | sock_put((struct sock *)msk); | 180 | sock_put((struct sock *)msk); |
| 181 | return err; | 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 | bool echo); | 801 | bool echo); |
| 802 | int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list); | 802 | int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list); |
| 803 | int mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list); | 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 | int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk, | 807 | int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk, |
| 805 | struct mptcp_pm_addr_entry *entry); | 808 | struct mptcp_pm_addr_entry *entry); |
| 806 | void mptcp_free_local_addr_list(struct mptcp_sock *msk); | 809 | void mptcp_free_local_addr_list(struct mptcp_sock *msk); |
| 807 | int mptcp_nl_cmd_announce(struct sk_buff *skb, struct genl_info *info); | 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 | void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk, | 813 | void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk, |
| 810 | const struct sock *ssk, gfp_t gfp); | 814 | const struct sock *ssk, gfp_t gfp); |