@@ -56,6 +56,36 @@ struct mptcp_info {
5656 __u32 mptcpi_last_ack_recv ;
5757};
5858
59+ enum {
60+ MPTCP_SUBFLOW_ATTR_UNSPEC ,
61+ MPTCP_SUBFLOW_ATTR_TOKEN_REM ,
62+ MPTCP_SUBFLOW_ATTR_TOKEN_LOC ,
63+ MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ ,
64+ MPTCP_SUBFLOW_ATTR_MAP_SEQ ,
65+ MPTCP_SUBFLOW_ATTR_MAP_SFSEQ ,
66+ MPTCP_SUBFLOW_ATTR_SSN_OFFSET ,
67+ MPTCP_SUBFLOW_ATTR_MAP_DATALEN ,
68+ MPTCP_SUBFLOW_ATTR_FLAGS ,
69+ MPTCP_SUBFLOW_ATTR_ID_REM ,
70+ MPTCP_SUBFLOW_ATTR_ID_LOC ,
71+ MPTCP_SUBFLOW_ATTR_PAD ,
72+
73+ __MPTCP_SUBFLOW_ATTR_MAX
74+ };
75+ #define MPTCP_SUBFLOW_ATTR_MAX (__MPTCP_SUBFLOW_ATTR_MAX - 1)
76+
77+ #define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0)
78+ #define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1)
79+ #define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2)
80+ #define MPTCP_SUBFLOW_FLAG_JOIN_LOC _BITUL(3)
81+ #define MPTCP_SUBFLOW_FLAG_BKUP_REM _BITUL(4)
82+ #define MPTCP_SUBFLOW_FLAG_BKUP_LOC _BITUL(5)
83+ #define MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED _BITUL(6)
84+ #define MPTCP_SUBFLOW_FLAG_CONNECTED _BITUL(7)
85+ #define MPTCP_SUBFLOW_FLAG_MAPVALID _BITUL(8)
86+
87+ #define rta_getattr (type , value ) (*(type *)RTA_DATA(value))
88+
5989static void die_perror (const char * msg )
6090{
6191 perror (msg );
@@ -167,6 +197,65 @@ static void print_info_msg(struct mptcp_info *info)
167197 printf ("bytes_acked: %llu\n" , info -> mptcpi_bytes_acked );
168198}
169199
200+ /*
201+ * 'print_subflow_info' is from 'mptcp_subflow_info'
202+ * which is a function in 'misc/ss.c' of iproute2.
203+ */
204+ static void print_subflow_info (struct rtattr * tb [])
205+ {
206+ u_int32_t flags = 0 ;
207+
208+ printf ("It's a mptcp subflow, the subflow info:\n" );
209+ if (tb [MPTCP_SUBFLOW_ATTR_FLAGS ]) {
210+ char caps [32 + 1 ] = { 0 }, * cap = & caps [0 ];
211+
212+ flags = rta_getattr (__u32 , tb [MPTCP_SUBFLOW_ATTR_FLAGS ]);
213+
214+ if (flags & MPTCP_SUBFLOW_FLAG_MCAP_REM )
215+ * cap ++ = 'M' ;
216+ if (flags & MPTCP_SUBFLOW_FLAG_MCAP_LOC )
217+ * cap ++ = 'm' ;
218+ if (flags & MPTCP_SUBFLOW_FLAG_JOIN_REM )
219+ * cap ++ = 'J' ;
220+ if (flags & MPTCP_SUBFLOW_FLAG_JOIN_LOC )
221+ * cap ++ = 'j' ;
222+ if (flags & MPTCP_SUBFLOW_FLAG_BKUP_REM )
223+ * cap ++ = 'B' ;
224+ if (flags & MPTCP_SUBFLOW_FLAG_BKUP_LOC )
225+ * cap ++ = 'b' ;
226+ if (flags & MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED )
227+ * cap ++ = 'e' ;
228+ if (flags & MPTCP_SUBFLOW_FLAG_CONNECTED )
229+ * cap ++ = 'c' ;
230+ if (flags & MPTCP_SUBFLOW_FLAG_MAPVALID )
231+ * cap ++ = 'v' ;
232+
233+ if (flags )
234+ printf (" flags:%s" , caps );
235+ }
236+ if (tb [MPTCP_SUBFLOW_ATTR_TOKEN_REM ] &&
237+ tb [MPTCP_SUBFLOW_ATTR_TOKEN_LOC ] &&
238+ tb [MPTCP_SUBFLOW_ATTR_ID_REM ] &&
239+ tb [MPTCP_SUBFLOW_ATTR_ID_LOC ])
240+ printf (" token:%04x(id:%u)/%04x(id:%u)" ,
241+ rta_getattr (__u32 , tb [MPTCP_SUBFLOW_ATTR_TOKEN_REM ]),
242+ rta_getattr (__u8 , tb [MPTCP_SUBFLOW_ATTR_ID_REM ]),
243+ rta_getattr (__u32 , tb [MPTCP_SUBFLOW_ATTR_TOKEN_LOC ]),
244+ rta_getattr (__u8 , tb [MPTCP_SUBFLOW_ATTR_ID_LOC ]));
245+ if (tb [MPTCP_SUBFLOW_ATTR_MAP_SEQ ])
246+ printf (" seq:%llu" ,
247+ rta_getattr (__u64 , tb [MPTCP_SUBFLOW_ATTR_MAP_SEQ ]));
248+ if (tb [MPTCP_SUBFLOW_ATTR_MAP_SFSEQ ])
249+ printf (" sfseq:%u" ,
250+ rta_getattr (__u32 , tb [MPTCP_SUBFLOW_ATTR_MAP_SFSEQ ]));
251+ if (tb [MPTCP_SUBFLOW_ATTR_SSN_OFFSET ])
252+ printf (" ssnoff:%u" ,
253+ rta_getattr (__u32 , tb [MPTCP_SUBFLOW_ATTR_SSN_OFFSET ]));
254+ if (tb [MPTCP_SUBFLOW_ATTR_MAP_DATALEN ])
255+ printf (" maplen:%u" ,
256+ rta_getattr (__u32 , tb [MPTCP_SUBFLOW_ATTR_MAP_DATALEN ]));
257+ }
258+
170259static void parse_nlmsg (struct nlmsghdr * nlh , __u32 proto )
171260{
172261 struct inet_diag_msg * r = NLMSG_DATA (nlh );
@@ -201,6 +290,7 @@ static void parse_nlmsg(struct nlmsghdr *nlh, __u32 proto)
201290
202291 parse_rtattr_nested (sfinfo , MPTCP_SUBFLOW_ATTR_MAX ,
203292 ulpinfo [INET_ULP_INFO_MPTCP ]);
293+ print_subflow_info (sfinfo );
204294 } else {
205295 printf ("It's a normal TCP!\n" );
206296 }
0 commit comments