Commit af09a341 authored by Dmitry Safonov's avatar Dmitry Safonov Committed by David S. Miller
Browse files

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: default avatarFrancesco Ruggeri <fruggeri@arista.com>
Signed-off-by: default avatarFrancesco Ruggeri <fruggeri@arista.com>
Co-developed-by: default avatarSalam Noureddine <noureddine@arista.com>
Signed-off-by: default avatarSalam Noureddine <noureddine@arista.com>
Signed-off-by: default avatarDmitry Safonov <dima@arista.com>
Acked-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0a3a8090
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -168,17 +168,24 @@ enum skb_drop_reason {
	 */
	SKB_DROP_REASON_TCP_MD5FAILURE,
	/**
	 * @SKB_DROP_REASON_TCP_AONOTFOUND: no TCP-AO hash and one was expected
	 * @SKB_DROP_REASON_TCP_AONOTFOUND: no TCP-AO hash and one was expected,
	 * corresponding to LINUX_MIB_TCPAOREQUIRED
	 */
	SKB_DROP_REASON_TCP_AONOTFOUND,
	/**
	 * @SKB_DROP_REASON_TCP_AOUNEXPECTED: TCP-AO hash is present and it
	 * was not expected.
	 * was not expected, corresponding to LINUX_MIB_TCPAOKEYNOTFOUND
	 */
	SKB_DROP_REASON_TCP_AOUNEXPECTED,
	/** @SKB_DROP_REASON_TCP_AOKEYNOTFOUND: TCP-AO key is unknown */
	/**
	 * @SKB_DROP_REASON_TCP_AOKEYNOTFOUND: TCP-AO key is unknown,
	 * corresponding to LINUX_MIB_TCPAOKEYNOTFOUND
	 */
	SKB_DROP_REASON_TCP_AOKEYNOTFOUND,
	/** @SKB_DROP_REASON_TCP_AOFAILURE: TCP-AO hash is wrong */
	/**
	 * @SKB_DROP_REASON_TCP_AOFAILURE: TCP-AO hash is wrong,
	 * corresponding to LINUX_MIB_TCPAOBAD
	 */
	SKB_DROP_REASON_TCP_AOFAILURE,
	/**
	 * @SKB_DROP_REASON_SOCKET_BACKLOG: failed to add skb to socket backlog (
+11 −4
Original line number Diff line number Diff line
@@ -2712,7 +2712,7 @@ static inline int tcp_parse_auth_options(const struct tcphdr *th,
}

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

	ao_key = tcp_ao_do_lookup(sk, saddr, family, -1, -1);
	if (ao_info->ao_required || ao_key)
	if (ao_info->ao_required || ao_key) {
		if (stat_inc) {
			NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOREQUIRED);
			atomic64_inc(&ao_info->counters.ao_required);
		}
		return true;
	}
#endif
	return false;
}
@@ -2747,9 +2752,11 @@ tcp_inbound_hash(struct sock *sk, const struct request_sock *req,
		return SKB_DROP_REASON_TCP_AUTH_HDR;

	if (req) {
		if (tcp_rsk_used_ao(req) != !!aoh)
		if (tcp_rsk_used_ao(req) != !!aoh) {
			NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD);
			return SKB_DROP_REASON_TCP_AOFAILURE;
		}
	}

	/* sdif set, means packet ingressed via a device
	 * in an L3 domain and dif is set to the l3mdev
@@ -2763,7 +2770,7 @@ tcp_inbound_hash(struct sock *sk, const struct request_sock *req,
		 * the last key is impossible to remove, so there's
		 * always at least one current_key.
		 */
		if (tcp_ao_required(sk, saddr, family))
		if (tcp_ao_required(sk, saddr, family, true))
			return SKB_DROP_REASON_TCP_AONOTFOUND;
		if (unlikely(tcp_md5_do_lookup(sk, l3index, saddr, family))) {
			NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
+10 −0
Original line number Diff line number Diff line
@@ -19,6 +19,13 @@ struct tcp_ao_hdr {
	u8	rnext_keyid;
};

struct tcp_ao_counters {
	atomic64_t	pkt_good;
	atomic64_t	pkt_bad;
	atomic64_t	key_not_found;
	atomic64_t	ao_required;
};

struct tcp_ao_key {
	struct hlist_node	node;
	union tcp_ao_addr	addr;
@@ -33,6 +40,8 @@ struct tcp_ao_key {
	u8			rcvid;
	u8			maclen;
	struct rcu_head		rcu;
	atomic64_t		pkt_good;
	atomic64_t		pkt_bad;
	u8			traffic_keys[];
};

@@ -81,6 +90,7 @@ struct tcp_ao_info {
	 */
	struct tcp_ao_key	*current_key;
	struct tcp_ao_key	*rnext_key;
	struct tcp_ao_counters	counters;
	u32			ao_required	:1,
				__unused	:31;
	__be32			lisn;
+4 −0
Original line number Diff line number Diff line
@@ -297,6 +297,10 @@ enum
	LINUX_MIB_TCPMIGRATEREQSUCCESS,		/* TCPMigrateReqSuccess */
	LINUX_MIB_TCPMIGRATEREQFAILURE,		/* TCPMigrateReqFailure */
	LINUX_MIB_TCPPLBREHASH,			/* TCPPLBRehash */
	LINUX_MIB_TCPAOREQUIRED,		/* TCPAORequired */
	LINUX_MIB_TCPAOBAD,			/* TCPAOBad */
	LINUX_MIB_TCPAOKEYNOTFOUND,		/* TCPAOKeyNotFound */
	LINUX_MIB_TCPAOGOOD,			/* TCPAOGood */
	__LINUX_MIB_MAX
};

+7 −1
Original line number Diff line number Diff line
@@ -404,9 +404,15 @@ struct tcp_ao_info_opt { /* setsockopt(TCP_AO_INFO) */
	__u32   set_current	:1,	/* corresponding ::current_key */
		set_rnext	:1,	/* corresponding ::rnext */
		ao_required	:1,	/* don't accept non-AO connects */
		reserved	:29;	/* must be 0 */
		set_counters	:1,	/* set/clear ::pkt_* counters */
		reserved	:28;	/* must be 0 */
	__u16	reserved2;		/* padding, must be 0 */
	__u8	current_key;		/* KeyID to set as Current_key */
	__u8	rnext;			/* KeyID to set as Rnext_key */
	__u64	pkt_good;		/* verified segments */
	__u64	pkt_bad;		/* failed verification */
	__u64	pkt_key_not_found;	/* could not find a key to verify */
	__u64	pkt_ao_required;	/* segments missing TCP-AO sign */
} __attribute__((aligned(8)));

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