Skip to content

Commit af09a34

Browse files
0x7f454c46davem330
authored andcommitted
net/tcp: Add TCP-AO segments counters
Introduce segment counters that are useful for troubleshooting/debugging as well as for writing tests. Now there are global snmp counters as well as per-socket and per-key. Co-developed-by: Francesco Ruggeri <[email protected]> Signed-off-by: Francesco Ruggeri <[email protected]> Co-developed-by: Salam Noureddine <[email protected]> Signed-off-by: Salam Noureddine <[email protected]> Signed-off-by: Dmitry Safonov <[email protected]> Acked-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0a3a809 commit af09a34

File tree

9 files changed

+77
-15
lines changed

9 files changed

+77
-15
lines changed

include/net/dropreason-core.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,17 +168,24 @@ enum skb_drop_reason {
168168
*/
169169
SKB_DROP_REASON_TCP_MD5FAILURE,
170170
/**
171-
* @SKB_DROP_REASON_TCP_AONOTFOUND: no TCP-AO hash and one was expected
171+
* @SKB_DROP_REASON_TCP_AONOTFOUND: no TCP-AO hash and one was expected,
172+
* corresponding to LINUX_MIB_TCPAOREQUIRED
172173
*/
173174
SKB_DROP_REASON_TCP_AONOTFOUND,
174175
/**
175176
* @SKB_DROP_REASON_TCP_AOUNEXPECTED: TCP-AO hash is present and it
176-
* was not expected.
177+
* was not expected, corresponding to LINUX_MIB_TCPAOKEYNOTFOUND
177178
*/
178179
SKB_DROP_REASON_TCP_AOUNEXPECTED,
179-
/** @SKB_DROP_REASON_TCP_AOKEYNOTFOUND: TCP-AO key is unknown */
180+
/**
181+
* @SKB_DROP_REASON_TCP_AOKEYNOTFOUND: TCP-AO key is unknown,
182+
* corresponding to LINUX_MIB_TCPAOKEYNOTFOUND
183+
*/
180184
SKB_DROP_REASON_TCP_AOKEYNOTFOUND,
181-
/** @SKB_DROP_REASON_TCP_AOFAILURE: TCP-AO hash is wrong */
185+
/**
186+
* @SKB_DROP_REASON_TCP_AOFAILURE: TCP-AO hash is wrong,
187+
* corresponding to LINUX_MIB_TCPAOBAD
188+
*/
182189
SKB_DROP_REASON_TCP_AOFAILURE,
183190
/**
184191
* @SKB_DROP_REASON_SOCKET_BACKLOG: failed to add skb to socket backlog (

include/net/tcp.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2712,7 +2712,7 @@ static inline int tcp_parse_auth_options(const struct tcphdr *th,
27122712
}
27132713

27142714
static inline bool tcp_ao_required(struct sock *sk, const void *saddr,
2715-
int family)
2715+
int family, bool stat_inc)
27162716
{
27172717
#ifdef CONFIG_TCP_AO
27182718
struct tcp_ao_info *ao_info;
@@ -2724,8 +2724,13 @@ static inline bool tcp_ao_required(struct sock *sk, const void *saddr,
27242724
return false;
27252725

27262726
ao_key = tcp_ao_do_lookup(sk, saddr, family, -1, -1);
2727-
if (ao_info->ao_required || ao_key)
2727+
if (ao_info->ao_required || ao_key) {
2728+
if (stat_inc) {
2729+
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOREQUIRED);
2730+
atomic64_inc(&ao_info->counters.ao_required);
2731+
}
27282732
return true;
2733+
}
27292734
#endif
27302735
return false;
27312736
}
@@ -2747,8 +2752,10 @@ tcp_inbound_hash(struct sock *sk, const struct request_sock *req,
27472752
return SKB_DROP_REASON_TCP_AUTH_HDR;
27482753

27492754
if (req) {
2750-
if (tcp_rsk_used_ao(req) != !!aoh)
2755+
if (tcp_rsk_used_ao(req) != !!aoh) {
2756+
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD);
27512757
return SKB_DROP_REASON_TCP_AOFAILURE;
2758+
}
27522759
}
27532760

27542761
/* sdif set, means packet ingressed via a device
@@ -2763,7 +2770,7 @@ tcp_inbound_hash(struct sock *sk, const struct request_sock *req,
27632770
* the last key is impossible to remove, so there's
27642771
* always at least one current_key.
27652772
*/
2766-
if (tcp_ao_required(sk, saddr, family))
2773+
if (tcp_ao_required(sk, saddr, family, true))
27672774
return SKB_DROP_REASON_TCP_AONOTFOUND;
27682775
if (unlikely(tcp_md5_do_lookup(sk, l3index, saddr, family))) {
27692776
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);

include/net/tcp_ao.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ struct tcp_ao_hdr {
1919
u8 rnext_keyid;
2020
};
2121

22+
struct tcp_ao_counters {
23+
atomic64_t pkt_good;
24+
atomic64_t pkt_bad;
25+
atomic64_t key_not_found;
26+
atomic64_t ao_required;
27+
};
28+
2229
struct tcp_ao_key {
2330
struct hlist_node node;
2431
union tcp_ao_addr addr;
@@ -33,6 +40,8 @@ struct tcp_ao_key {
3340
u8 rcvid;
3441
u8 maclen;
3542
struct rcu_head rcu;
43+
atomic64_t pkt_good;
44+
atomic64_t pkt_bad;
3645
u8 traffic_keys[];
3746
};
3847

@@ -81,6 +90,7 @@ struct tcp_ao_info {
8190
*/
8291
struct tcp_ao_key *current_key;
8392
struct tcp_ao_key *rnext_key;
93+
struct tcp_ao_counters counters;
8494
u32 ao_required :1,
8595
__unused :31;
8696
__be32 lisn;

include/uapi/linux/snmp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,10 @@ enum
297297
LINUX_MIB_TCPMIGRATEREQSUCCESS, /* TCPMigrateReqSuccess */
298298
LINUX_MIB_TCPMIGRATEREQFAILURE, /* TCPMigrateReqFailure */
299299
LINUX_MIB_TCPPLBREHASH, /* TCPPLBRehash */
300+
LINUX_MIB_TCPAOREQUIRED, /* TCPAORequired */
301+
LINUX_MIB_TCPAOBAD, /* TCPAOBad */
302+
LINUX_MIB_TCPAOKEYNOTFOUND, /* TCPAOKeyNotFound */
303+
LINUX_MIB_TCPAOGOOD, /* TCPAOGood */
300304
__LINUX_MIB_MAX
301305
};
302306

include/uapi/linux/tcp.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,15 @@ struct tcp_ao_info_opt { /* setsockopt(TCP_AO_INFO) */
404404
__u32 set_current :1, /* corresponding ::current_key */
405405
set_rnext :1, /* corresponding ::rnext */
406406
ao_required :1, /* don't accept non-AO connects */
407-
reserved :29; /* must be 0 */
407+
set_counters :1, /* set/clear ::pkt_* counters */
408+
reserved :28; /* must be 0 */
409+
__u16 reserved2; /* padding, must be 0 */
408410
__u8 current_key; /* KeyID to set as Current_key */
409411
__u8 rnext; /* KeyID to set as Rnext_key */
412+
__u64 pkt_good; /* verified segments */
413+
__u64 pkt_bad; /* failed verification */
414+
__u64 pkt_key_not_found; /* could not find a key to verify */
415+
__u64 pkt_ao_required; /* segments missing TCP-AO sign */
410416
} __attribute__((aligned(8)));
411417

412418
/* setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, ...) */

net/ipv4/proc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ static const struct snmp_mib snmp4_net_list[] = {
299299
SNMP_MIB_ITEM("TCPMigrateReqSuccess", LINUX_MIB_TCPMIGRATEREQSUCCESS),
300300
SNMP_MIB_ITEM("TCPMigrateReqFailure", LINUX_MIB_TCPMIGRATEREQFAILURE),
301301
SNMP_MIB_ITEM("TCPPLBRehash", LINUX_MIB_TCPPLBREHASH),
302+
SNMP_MIB_ITEM("TCPAORequired", LINUX_MIB_TCPAOREQUIRED),
303+
SNMP_MIB_ITEM("TCPAOBad", LINUX_MIB_TCPAOBAD),
304+
SNMP_MIB_ITEM("TCPAOKeyNotFound", LINUX_MIB_TCPAOKEYNOTFOUND),
305+
SNMP_MIB_ITEM("TCPAOGood", LINUX_MIB_TCPAOGOOD),
302306
SNMP_MIB_SENTINEL
303307
};
304308

net/ipv4/tcp_ao.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ static struct tcp_ao_key *tcp_ao_copy_key(struct sock *sk,
182182
*new_key = *key;
183183
INIT_HLIST_NODE(&new_key->node);
184184
tcp_sigpool_get(new_key->tcp_sigpool_id);
185+
atomic64_set(&new_key->pkt_good, 0);
186+
atomic64_set(&new_key->pkt_bad, 0);
185187

186188
return new_key;
187189
}
@@ -771,8 +773,12 @@ tcp_ao_verify_hash(const struct sock *sk, const struct sk_buff *skb,
771773
const struct tcphdr *th = tcp_hdr(skb);
772774
void *hash_buf = NULL;
773775

774-
if (maclen != tcp_ao_maclen(key))
776+
if (maclen != tcp_ao_maclen(key)) {
777+
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD);
778+
atomic64_inc(&info->counters.pkt_bad);
779+
atomic64_inc(&key->pkt_bad);
775780
return SKB_DROP_REASON_TCP_AOFAILURE;
781+
}
776782

777783
hash_buf = kmalloc(tcp_ao_digest_size(key), GFP_ATOMIC);
778784
if (!hash_buf)
@@ -782,9 +788,15 @@ tcp_ao_verify_hash(const struct sock *sk, const struct sk_buff *skb,
782788
tcp_ao_hash_skb(family, hash_buf, key, sk, skb, traffic_key,
783789
(phash - (u8 *)th), sne);
784790
if (memcmp(phash, hash_buf, maclen)) {
791+
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD);
792+
atomic64_inc(&info->counters.pkt_bad);
793+
atomic64_inc(&key->pkt_bad);
785794
kfree(hash_buf);
786795
return SKB_DROP_REASON_TCP_AOFAILURE;
787796
}
797+
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOGOOD);
798+
atomic64_inc(&info->counters.pkt_good);
799+
atomic64_inc(&key->pkt_good);
788800
kfree(hash_buf);
789801
return SKB_NOT_DROPPED_YET;
790802
}
@@ -804,8 +816,10 @@ tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb,
804816
u32 sne = 0;
805817

806818
info = rcu_dereference(tcp_sk(sk)->ao_info);
807-
if (!info)
819+
if (!info) {
820+
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOKEYNOTFOUND);
808821
return SKB_DROP_REASON_TCP_AOUNEXPECTED;
822+
}
809823

810824
if (unlikely(th->syn)) {
811825
sisn = th->seq;
@@ -900,6 +914,8 @@ tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb,
900914
return ret;
901915

902916
key_not_found:
917+
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOKEYNOTFOUND);
918+
atomic64_inc(&info->counters.key_not_found);
903919
return SKB_DROP_REASON_TCP_AOKEYNOTFOUND;
904920
}
905921

@@ -1483,6 +1499,8 @@ static int tcp_ao_add_cmd(struct sock *sk, unsigned short int family,
14831499
key->keyflags = cmd.keyflags;
14841500
key->sndid = cmd.sndid;
14851501
key->rcvid = cmd.rcvid;
1502+
atomic64_set(&key->pkt_good, 0);
1503+
atomic64_set(&key->pkt_bad, 0);
14861504

14871505
ret = tcp_ao_parse_crypto(&cmd, key);
14881506
if (ret < 0)
@@ -1699,7 +1717,7 @@ static int tcp_ao_info_cmd(struct sock *sk, unsigned short int family,
16991717
return -EINVAL;
17001718
}
17011719

1702-
if (cmd.reserved != 0)
1720+
if (cmd.reserved != 0 || cmd.reserved2 != 0)
17031721
return -EINVAL;
17041722

17051723
ao_info = setsockopt_ao_info(sk);
@@ -1734,6 +1752,12 @@ static int tcp_ao_info_cmd(struct sock *sk, unsigned short int family,
17341752
goto out;
17351753
}
17361754
}
1755+
if (cmd.set_counters) {
1756+
atomic64_set(&ao_info->counters.pkt_good, cmd.pkt_good);
1757+
atomic64_set(&ao_info->counters.pkt_bad, cmd.pkt_bad);
1758+
atomic64_set(&ao_info->counters.key_not_found, cmd.pkt_key_not_found);
1759+
atomic64_set(&ao_info->counters.ao_required, cmd.pkt_ao_required);
1760+
}
17371761

17381762
ao_info->ao_required = cmd.ao_required;
17391763
if (new_current)

net/ipv4/tcp_ipv4.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1531,7 +1531,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, int optname,
15311531
/* Don't allow keys for peers that have a matching TCP-AO key.
15321532
* See the comment in tcp_ao_add_cmd()
15331533
*/
1534-
if (tcp_ao_required(sk, addr, AF_INET))
1534+
if (tcp_ao_required(sk, addr, AF_INET, false))
15351535
return -EKEYREJECTED;
15361536

15371537
return tcp_md5_do_add(sk, addr, AF_INET, prefixlen, l3index, flags,

net/ipv6/tcp_ipv6.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
661661
/* Don't allow keys for peers that have a matching TCP-AO key.
662662
* See the comment in tcp_ao_add_cmd()
663663
*/
664-
if (tcp_ao_required(sk, addr, AF_INET))
664+
if (tcp_ao_required(sk, addr, AF_INET, false))
665665
return -EKEYREJECTED;
666666
return tcp_md5_do_add(sk, addr,
667667
AF_INET, prefixlen, l3index, flags,
@@ -673,7 +673,7 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
673673
/* Don't allow keys for peers that have a matching TCP-AO key.
674674
* See the comment in tcp_ao_add_cmd()
675675
*/
676-
if (tcp_ao_required(sk, addr, AF_INET6))
676+
if (tcp_ao_required(sk, addr, AF_INET6, false))
677677
return -EKEYREJECTED;
678678

679679
return tcp_md5_do_add(sk, addr, AF_INET6, prefixlen, l3index, flags,

0 commit comments

Comments
 (0)