Skip to content

Commit b911c97

Browse files
Florian Westphaldavem330
authored andcommitted
mptcp: add netlink event support
Allow userspace (mptcpd) to subscribe to mptcp genl multicast events. This implementation reuses the same event API as the mptcp kernel fork to ease integration of existing tools, e.g. mptcpd. Supported events include: 1. start and close of an mptcp connection 2. start and close of subflows (joins) 3. announce and withdrawals of addresses 4. subflow priority (backup/non-backup) change. Reviewed-by: Matthieu Baerts <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4d54cc3 commit b911c97

File tree

5 files changed

+364
-7
lines changed

5 files changed

+364
-7
lines changed

include/uapi/linux/mptcp.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ enum {
3636
/* netlink interface */
3737
#define MPTCP_PM_NAME "mptcp_pm"
3838
#define MPTCP_PM_CMD_GRP_NAME "mptcp_pm_cmds"
39+
#define MPTCP_PM_EV_GRP_NAME "mptcp_pm_events"
3940
#define MPTCP_PM_VER 0x1
4041

4142
/*
@@ -104,4 +105,77 @@ struct mptcp_info {
104105
__u64 mptcpi_rcv_nxt;
105106
};
106107

108+
/*
109+
* MPTCP_EVENT_CREATED: token, family, saddr4 | saddr6, daddr4 | daddr6,
110+
* sport, dport
111+
* A new MPTCP connection has been created. It is the good time to allocate
112+
* memory and send ADD_ADDR if needed. Depending on the traffic-patterns
113+
* it can take a long time until the MPTCP_EVENT_ESTABLISHED is sent.
114+
*
115+
* MPTCP_EVENT_ESTABLISHED: token, family, saddr4 | saddr6, daddr4 | daddr6,
116+
* sport, dport
117+
* A MPTCP connection is established (can start new subflows).
118+
*
119+
* MPTCP_EVENT_CLOSED: token
120+
* A MPTCP connection has stopped.
121+
*
122+
* MPTCP_EVENT_ANNOUNCED: token, rem_id, family, daddr4 | daddr6 [, dport]
123+
* A new address has been announced by the peer.
124+
*
125+
* MPTCP_EVENT_REMOVED: token, rem_id
126+
* An address has been lost by the peer.
127+
*
128+
* MPTCP_EVENT_SUB_ESTABLISHED: token, family, saddr4 | saddr6,
129+
* daddr4 | daddr6, sport, dport, backup,
130+
* if_idx [, error]
131+
* A new subflow has been established. 'error' should not be set.
132+
*
133+
* MPTCP_EVENT_SUB_CLOSED: token, family, saddr4 | saddr6, daddr4 | daddr6,
134+
* sport, dport, backup, if_idx [, error]
135+
* A subflow has been closed. An error (copy of sk_err) could be set if an
136+
* error has been detected for this subflow.
137+
*
138+
* MPTCP_EVENT_SUB_PRIORITY: token, family, saddr4 | saddr6, daddr4 | daddr6,
139+
* sport, dport, backup, if_idx [, error]
140+
* The priority of a subflow has changed. 'error' should not be set.
141+
*/
142+
enum mptcp_event_type {
143+
MPTCP_EVENT_UNSPEC = 0,
144+
MPTCP_EVENT_CREATED = 1,
145+
MPTCP_EVENT_ESTABLISHED = 2,
146+
MPTCP_EVENT_CLOSED = 3,
147+
148+
MPTCP_EVENT_ANNOUNCED = 6,
149+
MPTCP_EVENT_REMOVED = 7,
150+
151+
MPTCP_EVENT_SUB_ESTABLISHED = 10,
152+
MPTCP_EVENT_SUB_CLOSED = 11,
153+
154+
MPTCP_EVENT_SUB_PRIORITY = 13,
155+
};
156+
157+
enum mptcp_event_attr {
158+
MPTCP_ATTR_UNSPEC = 0,
159+
160+
MPTCP_ATTR_TOKEN, /* u32 */
161+
MPTCP_ATTR_FAMILY, /* u16 */
162+
MPTCP_ATTR_LOC_ID, /* u8 */
163+
MPTCP_ATTR_REM_ID, /* u8 */
164+
MPTCP_ATTR_SADDR4, /* be32 */
165+
MPTCP_ATTR_SADDR6, /* struct in6_addr */
166+
MPTCP_ATTR_DADDR4, /* be32 */
167+
MPTCP_ATTR_DADDR6, /* struct in6_addr */
168+
MPTCP_ATTR_SPORT, /* be16 */
169+
MPTCP_ATTR_DPORT, /* be16 */
170+
MPTCP_ATTR_BACKUP, /* u8 */
171+
MPTCP_ATTR_ERROR, /* u8 */
172+
MPTCP_ATTR_FLAGS, /* u16 */
173+
MPTCP_ATTR_TIMEOUT, /* u32 */
174+
MPTCP_ATTR_IF_IDX, /* s32 */
175+
176+
__MPTCP_ATTR_AFTER_LAST
177+
};
178+
179+
#define MPTCP_ATTR_MAX (__MPTCP_ATTR_AFTER_LAST - 1)
180+
107181
#endif /* _UAPI_MPTCP_H */

net/mptcp/pm.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ void mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ssk, int
7575
pr_debug("msk=%p, token=%u side=%d", msk, msk->token, server_side);
7676

7777
WRITE_ONCE(pm->server_side, server_side);
78+
mptcp_event(MPTCP_EVENT_CREATED, msk, ssk, GFP_ATOMIC);
7879
}
7980

8081
bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk)
@@ -122,13 +123,10 @@ static bool mptcp_pm_schedule_work(struct mptcp_sock *msk,
122123
void mptcp_pm_fully_established(struct mptcp_sock *msk, const struct sock *ssk, gfp_t gfp)
123124
{
124125
struct mptcp_pm_data *pm = &msk->pm;
126+
bool announce = false;
125127

126128
pr_debug("msk=%p", msk);
127129

128-
/* try to avoid acquiring the lock below */
129-
if (!READ_ONCE(pm->work_pending))
130-
return;
131-
132130
spin_lock_bh(&pm->lock);
133131

134132
/* mptcp_pm_fully_established() can be invoked by multiple
@@ -138,9 +136,15 @@ void mptcp_pm_fully_established(struct mptcp_sock *msk, const struct sock *ssk,
138136
if (READ_ONCE(pm->work_pending) &&
139137
!(msk->pm.status & BIT(MPTCP_PM_ALREADY_ESTABLISHED)))
140138
mptcp_pm_schedule_work(msk, MPTCP_PM_ESTABLISHED);
141-
msk->pm.status |= BIT(MPTCP_PM_ALREADY_ESTABLISHED);
142139

140+
if ((msk->pm.status & BIT(MPTCP_PM_ALREADY_ESTABLISHED)) == 0)
141+
announce = true;
142+
143+
msk->pm.status |= BIT(MPTCP_PM_ALREADY_ESTABLISHED);
143144
spin_unlock_bh(&pm->lock);
145+
146+
if (announce)
147+
mptcp_event(MPTCP_EVENT_ESTABLISHED, msk, ssk, gfp);
144148
}
145149

146150
void mptcp_pm_connection_closed(struct mptcp_sock *msk)
@@ -179,6 +183,8 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
179183
pr_debug("msk=%p remote_id=%d accept=%d", msk, addr->id,
180184
READ_ONCE(pm->accept_addr));
181185

186+
mptcp_event_addr_announced(msk, addr);
187+
182188
spin_lock_bh(&pm->lock);
183189

184190
if (!READ_ONCE(pm->accept_addr)) {
@@ -205,6 +211,8 @@ void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id)
205211

206212
pr_debug("msk=%p remote_id=%d", msk, rm_id);
207213

214+
mptcp_event_addr_removed(msk, rm_id);
215+
208216
spin_lock_bh(&pm->lock);
209217
mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED);
210218
pm->rm_id = rm_id;
@@ -217,6 +225,8 @@ void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup)
217225

218226
pr_debug("subflow->backup=%d, bkup=%d\n", subflow->backup, bkup);
219227
subflow->backup = bkup;
228+
229+
mptcp_event(MPTCP_EVENT_SUB_PRIORITY, mptcp_sk(subflow->conn), sk, GFP_ATOMIC);
220230
}
221231

222232
/* path manager helpers */

0 commit comments

Comments
 (0)