Skip to content

Commit 1729cf1

Browse files
geliangtangkuba-moo
authored andcommitted
mptcp: create the listening socket for new port
This patch creates a listening socket when an address with a port-number is added by PM netlink. Then binds the new port to the socket, and listens for new connections. When the address is removed or the addresses are flushed by PM netlink, release the listening socket. Signed-off-by: Geliang Tang <geliangtang@gmail.com> Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 6208fd8 commit 1729cf1

File tree

4 files changed

+102
-6
lines changed

4 files changed

+102
-6
lines changed

net/mptcp/pm_netlink.c

+94-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct mptcp_pm_addr_entry {
2626
struct list_head list;
2727
struct mptcp_addr_info addr;
2828
struct rcu_head rcu;
29+
struct socket *lsk;
2930
};
3031

3132
struct mptcp_pm_add_entry {
@@ -678,6 +679,53 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
678679
return ret;
679680
}
680681

682+
static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
683+
struct mptcp_pm_addr_entry *entry)
684+
{
685+
struct sockaddr_storage addr;
686+
struct mptcp_sock *msk;
687+
struct socket *ssock;
688+
int backlog = 1024;
689+
int err;
690+
691+
err = sock_create_kern(sock_net(sk), entry->addr.family,
692+
SOCK_STREAM, IPPROTO_MPTCP, &entry->lsk);
693+
if (err)
694+
return err;
695+
696+
msk = mptcp_sk(entry->lsk->sk);
697+
if (!msk) {
698+
err = -EINVAL;
699+
goto out;
700+
}
701+
702+
ssock = __mptcp_nmpc_socket(msk);
703+
if (!ssock) {
704+
err = -EINVAL;
705+
goto out;
706+
}
707+
708+
mptcp_info2sockaddr(&entry->addr, &addr, entry->addr.family);
709+
err = kernel_bind(ssock, (struct sockaddr *)&addr,
710+
sizeof(struct sockaddr_in));
711+
if (err) {
712+
pr_warn("kernel_bind error, err=%d", err);
713+
goto out;
714+
}
715+
716+
err = kernel_listen(ssock, backlog);
717+
if (err) {
718+
pr_warn("kernel_listen error, err=%d", err);
719+
goto out;
720+
}
721+
722+
return 0;
723+
724+
out:
725+
sock_release(entry->lsk);
726+
return err;
727+
}
728+
681729
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
682730
{
683731
struct mptcp_pm_addr_entry *entry;
@@ -722,6 +770,8 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
722770
entry->addr.ifindex = 0;
723771
entry->addr.flags = 0;
724772
entry->addr.id = 0;
773+
entry->addr.port = 0;
774+
entry->lsk = NULL;
725775
ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
726776
if (ret < 0)
727777
kfree(entry);
@@ -891,9 +941,19 @@ static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
891941
}
892942

893943
*entry = addr;
944+
if (entry->addr.port) {
945+
ret = mptcp_pm_nl_create_listen_socket(skb->sk, entry);
946+
if (ret) {
947+
GENL_SET_ERR_MSG(info, "create listen socket error");
948+
kfree(entry);
949+
return ret;
950+
}
951+
}
894952
ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
895953
if (ret < 0) {
896954
GENL_SET_ERR_MSG(info, "too many addresses or duplicate one");
955+
if (entry->lsk)
956+
sock_release(entry->lsk);
897957
kfree(entry);
898958
return ret;
899959
}
@@ -977,6 +1037,38 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
9771037
return 0;
9781038
}
9791039

1040+
struct addr_entry_release_work {
1041+
struct rcu_work rwork;
1042+
struct mptcp_pm_addr_entry *entry;
1043+
};
1044+
1045+
static void mptcp_pm_release_addr_entry(struct work_struct *work)
1046+
{
1047+
struct addr_entry_release_work *w;
1048+
struct mptcp_pm_addr_entry *entry;
1049+
1050+
w = container_of(to_rcu_work(work), struct addr_entry_release_work, rwork);
1051+
entry = w->entry;
1052+
if (entry) {
1053+
if (entry->lsk)
1054+
sock_release(entry->lsk);
1055+
kfree(entry);
1056+
}
1057+
kfree(w);
1058+
}
1059+
1060+
static void mptcp_pm_free_addr_entry(struct mptcp_pm_addr_entry *entry)
1061+
{
1062+
struct addr_entry_release_work *w;
1063+
1064+
w = kmalloc(sizeof(*w), GFP_ATOMIC);
1065+
if (w) {
1066+
INIT_RCU_WORK(&w->rwork, mptcp_pm_release_addr_entry);
1067+
w->entry = entry;
1068+
queue_rcu_work(system_wq, &w->rwork);
1069+
}
1070+
}
1071+
9801072
static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
9811073
{
9821074
struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
@@ -1011,7 +1103,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
10111103
spin_unlock_bh(&pernet->lock);
10121104

10131105
mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
1014-
kfree_rcu(entry, rcu);
1106+
mptcp_pm_free_addr_entry(entry);
10151107

10161108
return ret;
10171109
}
@@ -1025,7 +1117,7 @@ static void __flush_addrs(struct net *net, struct list_head *list)
10251117
struct mptcp_pm_addr_entry, list);
10261118
mptcp_nl_remove_subflow_and_signal_addr(net, &cur->addr);
10271119
list_del_rcu(&cur->list);
1028-
kfree_rcu(cur, rcu);
1120+
mptcp_pm_free_addr_entry(cur);
10291121
}
10301122
}
10311123

net/mptcp/protocol.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static struct net_device mptcp_napi_dev;
5252
* completed yet or has failed, return the subflow socket.
5353
* Otherwise return NULL.
5454
*/
55-
static struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk)
55+
struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk)
5656
{
5757
if (!msk->subflow || READ_ONCE(msk->can_ack))
5858
return NULL;

net/mptcp/protocol.h

+4
Original file line numberDiff line numberDiff line change
@@ -538,11 +538,15 @@ void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
538538
struct mptcp_subflow_context *subflow);
539539
void mptcp_subflow_reset(struct sock *ssk);
540540
void mptcp_sock_graft(struct sock *sk, struct socket *parent);
541+
struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
541542

542543
/* called with sk socket lock held */
543544
int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
544545
const struct mptcp_addr_info *remote);
545546
int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock);
547+
void mptcp_info2sockaddr(const struct mptcp_addr_info *info,
548+
struct sockaddr_storage *addr,
549+
unsigned short family);
546550

547551
static inline void mptcp_subflow_tcp_fallback(struct sock *sk,
548552
struct mptcp_subflow_context *ctx)

net/mptcp/subflow.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1084,9 +1084,9 @@ void mptcpv6_handle_mapped(struct sock *sk, bool mapped)
10841084
}
10851085
#endif
10861086

1087-
static void mptcp_info2sockaddr(const struct mptcp_addr_info *info,
1088-
struct sockaddr_storage *addr,
1089-
unsigned short family)
1087+
void mptcp_info2sockaddr(const struct mptcp_addr_info *info,
1088+
struct sockaddr_storage *addr,
1089+
unsigned short family)
10901090
{
10911091
memset(addr, 0, sizeof(*addr));
10921092
addr->ss_family = family;

0 commit comments

Comments
 (0)