Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <fruggeri@arista.com>
Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Co-developed-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Acked-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Dmitry Safonov and committed by
David S. Miller
af09a341 0a3a8090

+77 -15
+11 -4
include/net/dropreason-core.h
··· 168 168 */ 169 169 SKB_DROP_REASON_TCP_MD5FAILURE, 170 170 /** 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 172 173 */ 173 174 SKB_DROP_REASON_TCP_AONOTFOUND, 174 175 /** 175 176 * @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 177 178 */ 178 179 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 + */ 180 184 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 + */ 182 189 SKB_DROP_REASON_TCP_AOFAILURE, 183 190 /** 184 191 * @SKB_DROP_REASON_SOCKET_BACKLOG: failed to add skb to socket backlog (
+11 -4
include/net/tcp.h
··· 2712 2712 } 2713 2713 2714 2714 static inline bool tcp_ao_required(struct sock *sk, const void *saddr, 2715 - int family) 2715 + int family, bool stat_inc) 2716 2716 { 2717 2717 #ifdef CONFIG_TCP_AO 2718 2718 struct tcp_ao_info *ao_info; ··· 2724 2724 return false; 2725 2725 2726 2726 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 + } 2728 2732 return true; 2733 + } 2729 2734 #endif 2730 2735 return false; 2731 2736 } ··· 2752 2747 return SKB_DROP_REASON_TCP_AUTH_HDR; 2753 2748 2754 2749 if (req) { 2755 - if (tcp_rsk_used_ao(req) != !!aoh) 2750 + if (tcp_rsk_used_ao(req) != !!aoh) { 2751 + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD); 2756 2752 return SKB_DROP_REASON_TCP_AOFAILURE; 2753 + } 2757 2754 } 2758 2755 2759 2756 /* sdif set, means packet ingressed via a device ··· 2770 2763 * the last key is impossible to remove, so there's 2771 2764 * always at least one current_key. 2772 2765 */ 2773 - if (tcp_ao_required(sk, saddr, family)) 2766 + if (tcp_ao_required(sk, saddr, family, true)) 2774 2767 return SKB_DROP_REASON_TCP_AONOTFOUND; 2775 2768 if (unlikely(tcp_md5_do_lookup(sk, l3index, saddr, family))) { 2776 2769 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
+10
include/net/tcp_ao.h
··· 19 19 u8 rnext_keyid; 20 20 }; 21 21 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 + 22 29 struct tcp_ao_key { 23 30 struct hlist_node node; 24 31 union tcp_ao_addr addr; ··· 40 33 u8 rcvid; 41 34 u8 maclen; 42 35 struct rcu_head rcu; 36 + atomic64_t pkt_good; 37 + atomic64_t pkt_bad; 43 38 u8 traffic_keys[]; 44 39 }; 45 40 ··· 90 81 */ 91 82 struct tcp_ao_key *current_key; 92 83 struct tcp_ao_key *rnext_key; 84 + struct tcp_ao_counters counters; 93 85 u32 ao_required :1, 94 86 __unused :31; 95 87 __be32 lisn;
+4
include/uapi/linux/snmp.h
··· 297 297 LINUX_MIB_TCPMIGRATEREQSUCCESS, /* TCPMigrateReqSuccess */ 298 298 LINUX_MIB_TCPMIGRATEREQFAILURE, /* TCPMigrateReqFailure */ 299 299 LINUX_MIB_TCPPLBREHASH, /* TCPPLBRehash */ 300 + LINUX_MIB_TCPAOREQUIRED, /* TCPAORequired */ 301 + LINUX_MIB_TCPAOBAD, /* TCPAOBad */ 302 + LINUX_MIB_TCPAOKEYNOTFOUND, /* TCPAOKeyNotFound */ 303 + LINUX_MIB_TCPAOGOOD, /* TCPAOGood */ 300 304 __LINUX_MIB_MAX 301 305 }; 302 306
+7 -1
include/uapi/linux/tcp.h
··· 404 404 __u32 set_current :1, /* corresponding ::current_key */ 405 405 set_rnext :1, /* corresponding ::rnext */ 406 406 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 */ 408 410 __u8 current_key; /* KeyID to set as Current_key */ 409 411 __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 */ 410 416 } __attribute__((aligned(8))); 411 417 412 418 /* setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, ...) */
+4
net/ipv4/proc.c
··· 299 299 SNMP_MIB_ITEM("TCPMigrateReqSuccess", LINUX_MIB_TCPMIGRATEREQSUCCESS), 300 300 SNMP_MIB_ITEM("TCPMigrateReqFailure", LINUX_MIB_TCPMIGRATEREQFAILURE), 301 301 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), 302 306 SNMP_MIB_SENTINEL 303 307 }; 304 308
+27 -3
net/ipv4/tcp_ao.c
··· 182 182 *new_key = *key; 183 183 INIT_HLIST_NODE(&new_key->node); 184 184 tcp_sigpool_get(new_key->tcp_sigpool_id); 185 + atomic64_set(&new_key->pkt_good, 0); 186 + atomic64_set(&new_key->pkt_bad, 0); 185 187 186 188 return new_key; 187 189 } ··· 773 771 const struct tcphdr *th = tcp_hdr(skb); 774 772 void *hash_buf = NULL; 775 773 776 - if (maclen != tcp_ao_maclen(key)) 774 + if (maclen != tcp_ao_maclen(key)) { 775 + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD); 776 + atomic64_inc(&info->counters.pkt_bad); 777 + atomic64_inc(&key->pkt_bad); 777 778 return SKB_DROP_REASON_TCP_AOFAILURE; 779 + } 778 780 779 781 hash_buf = kmalloc(tcp_ao_digest_size(key), GFP_ATOMIC); 780 782 if (!hash_buf) ··· 788 782 tcp_ao_hash_skb(family, hash_buf, key, sk, skb, traffic_key, 789 783 (phash - (u8 *)th), sne); 790 784 if (memcmp(phash, hash_buf, maclen)) { 785 + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD); 786 + atomic64_inc(&info->counters.pkt_bad); 787 + atomic64_inc(&key->pkt_bad); 791 788 kfree(hash_buf); 792 789 return SKB_DROP_REASON_TCP_AOFAILURE; 793 790 } 791 + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOGOOD); 792 + atomic64_inc(&info->counters.pkt_good); 793 + atomic64_inc(&key->pkt_good); 794 794 kfree(hash_buf); 795 795 return SKB_NOT_DROPPED_YET; 796 796 } ··· 816 804 u32 sne = 0; 817 805 818 806 info = rcu_dereference(tcp_sk(sk)->ao_info); 819 - if (!info) 807 + if (!info) { 808 + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOKEYNOTFOUND); 820 809 return SKB_DROP_REASON_TCP_AOUNEXPECTED; 810 + } 821 811 822 812 if (unlikely(th->syn)) { 823 813 sisn = th->seq; ··· 914 900 return ret; 915 901 916 902 key_not_found: 903 + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOKEYNOTFOUND); 904 + atomic64_inc(&info->counters.key_not_found); 917 905 return SKB_DROP_REASON_TCP_AOKEYNOTFOUND; 918 906 } 919 907 ··· 1499 1483 key->keyflags = cmd.keyflags; 1500 1484 key->sndid = cmd.sndid; 1501 1485 key->rcvid = cmd.rcvid; 1486 + atomic64_set(&key->pkt_good, 0); 1487 + atomic64_set(&key->pkt_bad, 0); 1502 1488 1503 1489 ret = tcp_ao_parse_crypto(&cmd, key); 1504 1490 if (ret < 0) ··· 1717 1699 return -EINVAL; 1718 1700 } 1719 1701 1720 - if (cmd.reserved != 0) 1702 + if (cmd.reserved != 0 || cmd.reserved2 != 0) 1721 1703 return -EINVAL; 1722 1704 1723 1705 ao_info = setsockopt_ao_info(sk); ··· 1751 1733 err = -ENOENT; 1752 1734 goto out; 1753 1735 } 1736 + } 1737 + if (cmd.set_counters) { 1738 + atomic64_set(&ao_info->counters.pkt_good, cmd.pkt_good); 1739 + atomic64_set(&ao_info->counters.pkt_bad, cmd.pkt_bad); 1740 + atomic64_set(&ao_info->counters.key_not_found, cmd.pkt_key_not_found); 1741 + atomic64_set(&ao_info->counters.ao_required, cmd.pkt_ao_required); 1754 1742 } 1755 1743 1756 1744 ao_info->ao_required = cmd.ao_required;
+1 -1
net/ipv4/tcp_ipv4.c
··· 1531 1531 /* Don't allow keys for peers that have a matching TCP-AO key. 1532 1532 * See the comment in tcp_ao_add_cmd() 1533 1533 */ 1534 - if (tcp_ao_required(sk, addr, AF_INET)) 1534 + if (tcp_ao_required(sk, addr, AF_INET, false)) 1535 1535 return -EKEYREJECTED; 1536 1536 1537 1537 return tcp_md5_do_add(sk, addr, AF_INET, prefixlen, l3index, flags,
+2 -2
net/ipv6/tcp_ipv6.c
··· 661 661 /* Don't allow keys for peers that have a matching TCP-AO key. 662 662 * See the comment in tcp_ao_add_cmd() 663 663 */ 664 - if (tcp_ao_required(sk, addr, AF_INET)) 664 + if (tcp_ao_required(sk, addr, AF_INET, false)) 665 665 return -EKEYREJECTED; 666 666 return tcp_md5_do_add(sk, addr, 667 667 AF_INET, prefixlen, l3index, flags, ··· 673 673 /* Don't allow keys for peers that have a matching TCP-AO key. 674 674 * See the comment in tcp_ao_add_cmd() 675 675 */ 676 - if (tcp_ao_required(sk, addr, AF_INET6)) 676 + if (tcp_ao_required(sk, addr, AF_INET6, false)) 677 677 return -EKEYREJECTED; 678 678 679 679 return tcp_md5_do_add(sk, addr, AF_INET6, prefixlen, l3index, flags,