408 lines · 8.3 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0+ *//* * Copyright (c) 2021 Taehee Yoo <ap420073@gmail.com> */#ifndef _NET_AMT_H_#define _NET_AMT_H_ #include <linux/siphash.h>#include <linux/jhash.h>#include <linux/netdevice.h>#include <net/gro_cells.h>#include <net/rtnetlink.h> enum amt_msg_type {	AMT_MSG_DISCOVERY = 1,	AMT_MSG_ADVERTISEMENT,	AMT_MSG_REQUEST,	AMT_MSG_MEMBERSHIP_QUERY,	AMT_MSG_MEMBERSHIP_UPDATE,	AMT_MSG_MULTICAST_DATA,	AMT_MSG_TEARDOWN,	__AMT_MSG_MAX,}; #define AMT_MSG_MAX (__AMT_MSG_MAX - 1) enum amt_ops {	/* A*B */	AMT_OPS_INT,	/* A+B */	AMT_OPS_UNI,	/* A-B */	AMT_OPS_SUB,	/* B-A */	AMT_OPS_SUB_REV,	__AMT_OPS_MAX,}; #define AMT_OPS_MAX (__AMT_OPS_MAX - 1) enum amt_filter {	AMT_FILTER_FWD,	AMT_FILTER_D_FWD,	AMT_FILTER_FWD_NEW,	AMT_FILTER_D_FWD_NEW,	AMT_FILTER_ALL,	AMT_FILTER_NONE_NEW,	AMT_FILTER_BOTH,	AMT_FILTER_BOTH_NEW,	__AMT_FILTER_MAX,}; #define AMT_FILTER_MAX (__AMT_FILTER_MAX - 1) enum amt_act {	AMT_ACT_GMI,	AMT_ACT_GMI_ZERO,	AMT_ACT_GT,	AMT_ACT_STATUS_FWD_NEW,	AMT_ACT_STATUS_D_FWD_NEW,	AMT_ACT_STATUS_NONE_NEW,	__AMT_ACT_MAX,}; #define AMT_ACT_MAX (__AMT_ACT_MAX - 1) enum amt_status {	AMT_STATUS_INIT,	AMT_STATUS_SENT_DISCOVERY,	AMT_STATUS_RECEIVED_DISCOVERY,	AMT_STATUS_SENT_ADVERTISEMENT,	AMT_STATUS_RECEIVED_ADVERTISEMENT,	AMT_STATUS_SENT_REQUEST,	AMT_STATUS_RECEIVED_REQUEST,	AMT_STATUS_SENT_QUERY,	AMT_STATUS_RECEIVED_QUERY,	AMT_STATUS_SENT_UPDATE,	AMT_STATUS_RECEIVED_UPDATE,	__AMT_STATUS_MAX,}; #define AMT_STATUS_MAX (__AMT_STATUS_MAX - 1) /* Gateway events only */enum amt_event {	AMT_EVENT_NONE,	AMT_EVENT_RECEIVE,	AMT_EVENT_SEND_DISCOVERY,	AMT_EVENT_SEND_REQUEST,	__AMT_EVENT_MAX,}; struct amt_header {#if defined(__LITTLE_ENDIAN_BITFIELD)	u8 type:4,	   version:4;#elif defined(__BIG_ENDIAN_BITFIELD)	u8 version:4,	   type:4;#else#error  "Please fix <asm/byteorder.h>"#endif} __packed; struct amt_header_discovery {#if defined(__LITTLE_ENDIAN_BITFIELD)	u32	type:4,		version:4,		reserved:24;#elif defined(__BIG_ENDIAN_BITFIELD)	u32	version:4,		type:4,		reserved:24;#else#error  "Please fix <asm/byteorder.h>"#endif	__be32	nonce;} __packed; struct amt_header_advertisement {#if defined(__LITTLE_ENDIAN_BITFIELD)	u32	type:4,		version:4,		reserved:24;#elif defined(__BIG_ENDIAN_BITFIELD)	u32	version:4,		type:4,		reserved:24;#else#error  "Please fix <asm/byteorder.h>"#endif	__be32	nonce;	__be32	ip4;} __packed; struct amt_header_request {#if defined(__LITTLE_ENDIAN_BITFIELD)	u32	type:4,		version:4,		reserved1:7,		p:1,		reserved2:16;#elif defined(__BIG_ENDIAN_BITFIELD)	u32	version:4,		type:4,		p:1,		reserved1:7,		reserved2:16;#else#error  "Please fix <asm/byteorder.h>"#endif	__be32	nonce;} __packed; struct amt_header_membership_query {#if defined(__LITTLE_ENDIAN_BITFIELD)	u64	type:4,		version:4,		reserved:6,		l:1,		g:1,		response_mac:48;#elif defined(__BIG_ENDIAN_BITFIELD)	u64	version:4,		type:4,		g:1,		l:1,		reserved:6,		response_mac:48;#else#error  "Please fix <asm/byteorder.h>"#endif	__be32	nonce;} __packed; struct amt_header_membership_update {#if defined(__LITTLE_ENDIAN_BITFIELD)	u64	type:4,		version:4,		reserved:8,		response_mac:48;#elif defined(__BIG_ENDIAN_BITFIELD)	u64	version:4,		type:4,		reserved:8,		response_mac:48;#else#error  "Please fix <asm/byteorder.h>"#endif	__be32	nonce;} __packed; struct amt_header_mcast_data {#if defined(__LITTLE_ENDIAN_BITFIELD)	u16	type:4,		version:4,		reserved:8;#elif defined(__BIG_ENDIAN_BITFIELD)	u16	version:4,		type:4,		reserved:8;#else#error  "Please fix <asm/byteorder.h>"#endif} __packed; struct amt_headers {	union {		struct amt_header_discovery discovery;		struct amt_header_advertisement advertisement;		struct amt_header_request request;		struct amt_header_membership_query query;		struct amt_header_membership_update update;		struct amt_header_mcast_data data;	};} __packed; struct amt_gw_headers {	union {		struct amt_header_discovery discovery;		struct amt_header_request request;		struct amt_header_membership_update update;	};} __packed; struct amt_relay_headers {	union {		struct amt_header_advertisement advertisement;		struct amt_header_membership_query query;		struct amt_header_mcast_data data;	};} __packed; struct amt_skb_cb {	struct amt_tunnel_list *tunnel;}; struct amt_tunnel_list {	struct list_head	list;	/* Protect All resources under an amt_tunne_list */	spinlock_t		lock;	struct amt_dev		*amt;	u32			nr_groups;	u32			nr_sources;	enum amt_status		status;	struct delayed_work	gc_wq;	__be16			source_port;	__be32			ip4;	__be32			nonce;	siphash_key_t		key;	u64			mac:48,				reserved:16;	struct rcu_head		rcu;	struct hlist_head	groups[];}; union amt_addr {	__be32			ip4;#if IS_ENABLED(CONFIG_IPV6)	struct in6_addr		ip6;#endif}; /* RFC 3810 * * When the router is in EXCLUDE mode, the router state is represented * by the notation EXCLUDE (X,Y), where X is called the "Requested List" * and Y is called the "Exclude List".  All sources, except those from * the Exclude List, will be forwarded by the router */enum amt_source_status {	AMT_SOURCE_STATUS_NONE,	/* Node of Requested List */	AMT_SOURCE_STATUS_FWD,	/* Node of Exclude List */	AMT_SOURCE_STATUS_D_FWD,}; /* protected by gnode->lock */struct amt_source_node {	struct hlist_node	node;	struct amt_group_node	*gnode;	struct delayed_work     source_timer;	union amt_addr		source_addr;	enum amt_source_status	status;#define AMT_SOURCE_OLD	0#define AMT_SOURCE_NEW	1	u8			flags;	struct rcu_head		rcu;}; /* Protected by amt_tunnel_list->lock */struct amt_group_node {	struct amt_dev		*amt;	union amt_addr		group_addr;	union amt_addr		host_addr;	bool			v6;	u8			filter_mode;	u32			nr_sources;	struct amt_tunnel_list	*tunnel_list;	struct hlist_node	node;	struct delayed_work     group_timer;	struct rcu_head		rcu;	struct hlist_head	sources[];}; #define AMT_MAX_EVENTS	16struct amt_events {	enum amt_event event;	struct sk_buff *skb;}; struct amt_dev {	struct net_device       *dev;	struct net_device       *stream_dev;	struct net		*net;	/* Global lock for amt device */	spinlock_t		lock;	/* Used only in relay mode */	struct list_head        tunnel_list;	struct gro_cells	gro_cells; 	/* Protected by RTNL */	struct delayed_work     discovery_wq;	/* Protected by RTNL */	struct delayed_work     req_wq;	/* Protected by RTNL */	struct delayed_work     secret_wq;	struct work_struct	event_wq;	/* AMT status */	enum amt_status		status;	/* Generated key */	siphash_key_t		key;	struct sock	  __rcu *sk;	u32			max_groups;	u32			max_sources;	u32			hash_buckets;	u32			hash_seed;	/* Default 128 */	u32                     max_tunnels;	/* Default 128 */	u32                     nr_tunnels;	/* Gateway or Relay mode */	u32                     mode;	/* Default 2268 */	__be16			relay_port;	/* Default 2268 */	__be16			gw_port;	/* Outer local ip */	__be32			local_ip;	/* Outer remote ip */	__be32			remote_ip;	/* Outer discovery ip */	__be32			discovery_ip;	/* Only used in gateway mode */	__be32			nonce;	/* Gateway sent request and received query */	bool			ready4;	bool			ready6;	u8			req_cnt;	u8			qi;	u64			qrv;	u64			qri;	/* Used only in gateway mode */	u64			mac:48,				reserved:16;	/* AMT gateway side message handler queue */	struct amt_events	events[AMT_MAX_EVENTS];	u8			event_idx;	u8			nr_events;}; #define AMT_TOS			0xc0#define AMT_IPHDR_OPTS		4#define AMT_IP6HDR_OPTS		8#define AMT_GC_INTERVAL		(30 * 1000)#define AMT_MAX_GROUP		32#define AMT_MAX_SOURCE		128#define AMT_HSIZE_SHIFT		8#define AMT_HSIZE		(1 << AMT_HSIZE_SHIFT) #define AMT_DISCOVERY_TIMEOUT	5000#define AMT_INIT_REQ_TIMEOUT	1#define AMT_INIT_QUERY_INTERVAL	125#define AMT_MAX_REQ_TIMEOUT	120#define AMT_MAX_REQ_COUNT	3#define AMT_SECRET_TIMEOUT	60000#define IANA_AMT_UDP_PORT	2268#define AMT_MAX_TUNNELS         128#define AMT_MAX_REQS		128#define AMT_GW_HLEN (sizeof(struct iphdr) + \		     sizeof(struct udphdr) + \		     sizeof(struct amt_gw_headers))#define AMT_RELAY_HLEN (sizeof(struct iphdr) + \		     sizeof(struct udphdr) + \		     sizeof(struct amt_relay_headers)) static inline bool netif_is_amt(const struct net_device *dev){	return dev->rtnl_link_ops && !strcmp(dev->rtnl_link_ops->kind, "amt");} static inline u64 amt_gmi(const struct amt_dev *amt){	return ((amt->qrv * amt->qi) + amt->qri) * 1000;} #endif /* _NET_AMT_H_ */