xref: /openbmc/linux/drivers/net/ipvlan/ipvlan.h (revision 40b9d1ab)
12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
22ad7bf36SMahesh Bandewar /*
32ad7bf36SMahesh Bandewar  * Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
42ad7bf36SMahesh Bandewar  */
52ad7bf36SMahesh Bandewar #ifndef __IPVLAN_H
62ad7bf36SMahesh Bandewar #define __IPVLAN_H
72ad7bf36SMahesh Bandewar 
82ad7bf36SMahesh Bandewar #include <linux/kernel.h>
92ad7bf36SMahesh Bandewar #include <linux/types.h>
102ad7bf36SMahesh Bandewar #include <linux/module.h>
112ad7bf36SMahesh Bandewar #include <linux/init.h>
122ad7bf36SMahesh Bandewar #include <linux/rculist.h>
132ad7bf36SMahesh Bandewar #include <linux/notifier.h>
142ad7bf36SMahesh Bandewar #include <linux/netdevice.h>
152ad7bf36SMahesh Bandewar #include <linux/etherdevice.h>
162ad7bf36SMahesh Bandewar #include <linux/if_arp.h>
172ad7bf36SMahesh Bandewar #include <linux/if_link.h>
182ad7bf36SMahesh Bandewar #include <linux/if_vlan.h>
192ad7bf36SMahesh Bandewar #include <linux/ip.h>
202ad7bf36SMahesh Bandewar #include <linux/inetdevice.h>
214fbae7d8SMahesh Bandewar #include <linux/netfilter.h>
22265de6d1SMahesh Bandewar #include <net/ip.h>
23265de6d1SMahesh Bandewar #include <net/ip6_route.h>
243133822fSFlorian Westphal #include <net/netns/generic.h>
252ad7bf36SMahesh Bandewar #include <net/rtnetlink.h>
262ad7bf36SMahesh Bandewar #include <net/route.h>
272ad7bf36SMahesh Bandewar #include <net/addrconf.h>
284fbae7d8SMahesh Bandewar #include <net/l3mdev.h>
292ad7bf36SMahesh Bandewar 
302ad7bf36SMahesh Bandewar #define IPVLAN_DRV	"ipvlan"
312ad7bf36SMahesh Bandewar #define IPV_DRV_VER	"0.1"
322ad7bf36SMahesh Bandewar 
332ad7bf36SMahesh Bandewar #define IPVLAN_HASH_SIZE	(1 << BITS_PER_BYTE)
342ad7bf36SMahesh Bandewar #define IPVLAN_HASH_MASK	(IPVLAN_HASH_SIZE - 1)
352ad7bf36SMahesh Bandewar 
362ad7bf36SMahesh Bandewar #define IPVLAN_MAC_FILTER_BITS	8
372ad7bf36SMahesh Bandewar #define IPVLAN_MAC_FILTER_SIZE	(1 << IPVLAN_MAC_FILTER_BITS)
382ad7bf36SMahesh Bandewar #define IPVLAN_MAC_FILTER_MASK	(IPVLAN_MAC_FILTER_SIZE - 1)
392ad7bf36SMahesh Bandewar 
40ba35f858SMahesh Bandewar #define IPVLAN_QBACKLOG_LIMIT	1000
41ba35f858SMahesh Bandewar 
422ad7bf36SMahesh Bandewar typedef enum {
432ad7bf36SMahesh Bandewar 	IPVL_IPV6 = 0,
442ad7bf36SMahesh Bandewar 	IPVL_ICMPV6,
452ad7bf36SMahesh Bandewar 	IPVL_IPV4,
462ad7bf36SMahesh Bandewar 	IPVL_ARP,
472ad7bf36SMahesh Bandewar } ipvl_hdr_type;
482ad7bf36SMahesh Bandewar 
492ad7bf36SMahesh Bandewar struct ipvl_pcpu_stats {
505665f48eSEric Dumazet 	u64_stats_t		rx_pkts;
515665f48eSEric Dumazet 	u64_stats_t		rx_bytes;
525665f48eSEric Dumazet 	u64_stats_t		rx_mcast;
535665f48eSEric Dumazet 	u64_stats_t		tx_pkts;
545665f48eSEric Dumazet 	u64_stats_t		tx_bytes;
552ad7bf36SMahesh Bandewar 	struct u64_stats_sync	syncp;
562ad7bf36SMahesh Bandewar 	u32			rx_errs;
572ad7bf36SMahesh Bandewar 	u32			tx_drps;
582ad7bf36SMahesh Bandewar };
592ad7bf36SMahesh Bandewar 
602ad7bf36SMahesh Bandewar struct ipvl_port;
612ad7bf36SMahesh Bandewar 
622ad7bf36SMahesh Bandewar struct ipvl_dev {
632ad7bf36SMahesh Bandewar 	struct net_device	*dev;
642ad7bf36SMahesh Bandewar 	struct list_head	pnode;
652ad7bf36SMahesh Bandewar 	struct ipvl_port	*port;
662ad7bf36SMahesh Bandewar 	struct net_device	*phy_dev;
672ad7bf36SMahesh Bandewar 	struct list_head	addrs;
686aa6395fSEric Dumazet 	struct ipvl_pcpu_stats	__percpu *pcpu_stats;
692ad7bf36SMahesh Bandewar 	DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE);
702ad7bf36SMahesh Bandewar 	netdev_features_t	sfeatures;
712ad7bf36SMahesh Bandewar 	u32			msg_enable;
7282308194SPaolo Abeni 	spinlock_t		addrs_lock;
732ad7bf36SMahesh Bandewar };
742ad7bf36SMahesh Bandewar 
752ad7bf36SMahesh Bandewar struct ipvl_addr {
762ad7bf36SMahesh Bandewar 	struct ipvl_dev		*master; /* Back pointer to master */
772ad7bf36SMahesh Bandewar 	union {
782ad7bf36SMahesh Bandewar 		struct in6_addr	ip6;	 /* IPv6 address on logical interface */
792ad7bf36SMahesh Bandewar 		struct in_addr	ip4;	 /* IPv4 address on logical interface */
802ad7bf36SMahesh Bandewar 	} ipu;
812ad7bf36SMahesh Bandewar #define ip6addr	ipu.ip6
822ad7bf36SMahesh Bandewar #define ip4addr ipu.ip4
832ad7bf36SMahesh Bandewar 	struct hlist_node	hlnode;  /* Hash-table linkage */
842ad7bf36SMahesh Bandewar 	struct list_head	anode;   /* logical-interface linkage */
852ad7bf36SMahesh Bandewar 	ipvl_hdr_type		atype;
86ab5b7013SMahesh Bandewar 	struct rcu_head		rcu;
872ad7bf36SMahesh Bandewar };
882ad7bf36SMahesh Bandewar 
892ad7bf36SMahesh Bandewar struct ipvl_port {
902ad7bf36SMahesh Bandewar 	struct net_device	*dev;
913133822fSFlorian Westphal 	possible_net_t		pnet;
922ad7bf36SMahesh Bandewar 	struct hlist_head	hlhead[IPVLAN_HASH_SIZE];
932ad7bf36SMahesh Bandewar 	struct list_head	ipvlans;
94ab5b7013SMahesh Bandewar 	u16			mode;
95a190d04dSMahesh Bandewar 	u16			flags;
96da36e13cSMahesh Bandewar 	u16			dev_id_start;
97ba35f858SMahesh Bandewar 	struct work_struct	wq;
98ba35f858SMahesh Bandewar 	struct sk_buff_head	backlog;
992ad7bf36SMahesh Bandewar 	int			count;
100009146d1SMahesh Bandewar 	struct ida		ida;
101*40b9d1abSMahesh Bandewar 	netdevice_tracker	dev_tracker;
1022ad7bf36SMahesh Bandewar };
1032ad7bf36SMahesh Bandewar 
104e2525360SMahesh Bandewar struct ipvl_skb_cb {
105e2525360SMahesh Bandewar 	bool tx_pkt;
106e2525360SMahesh Bandewar };
107e2525360SMahesh Bandewar #define IPVL_SKB_CB(_skb) ((struct ipvl_skb_cb *)&((_skb)->cb[0]))
108e2525360SMahesh Bandewar 
ipvlan_port_get_rcu(const struct net_device * d)1092ad7bf36SMahesh Bandewar static inline struct ipvl_port *ipvlan_port_get_rcu(const struct net_device *d)
1102ad7bf36SMahesh Bandewar {
1112ad7bf36SMahesh Bandewar 	return rcu_dereference(d->rx_handler_data);
1122ad7bf36SMahesh Bandewar }
1132ad7bf36SMahesh Bandewar 
ipvlan_port_get_rcu_bh(const struct net_device * d)1140fba37a3SWANG Cong static inline struct ipvl_port *ipvlan_port_get_rcu_bh(const struct net_device *d)
1150fba37a3SWANG Cong {
1160fba37a3SWANG Cong 	return rcu_dereference_bh(d->rx_handler_data);
1170fba37a3SWANG Cong }
1180fba37a3SWANG Cong 
ipvlan_port_get_rtnl(const struct net_device * d)1192ad7bf36SMahesh Bandewar static inline struct ipvl_port *ipvlan_port_get_rtnl(const struct net_device *d)
1202ad7bf36SMahesh Bandewar {
1212ad7bf36SMahesh Bandewar 	return rtnl_dereference(d->rx_handler_data);
1222ad7bf36SMahesh Bandewar }
1232ad7bf36SMahesh Bandewar 
ipvlan_is_private(const struct ipvl_port * port)124a190d04dSMahesh Bandewar static inline bool ipvlan_is_private(const struct ipvl_port *port)
125a190d04dSMahesh Bandewar {
126a190d04dSMahesh Bandewar 	return !!(port->flags & IPVLAN_F_PRIVATE);
127a190d04dSMahesh Bandewar }
128a190d04dSMahesh Bandewar 
ipvlan_mark_private(struct ipvl_port * port)129a190d04dSMahesh Bandewar static inline void ipvlan_mark_private(struct ipvl_port *port)
130a190d04dSMahesh Bandewar {
131a190d04dSMahesh Bandewar 	port->flags |= IPVLAN_F_PRIVATE;
132a190d04dSMahesh Bandewar }
133a190d04dSMahesh Bandewar 
ipvlan_clear_private(struct ipvl_port * port)134a190d04dSMahesh Bandewar static inline void ipvlan_clear_private(struct ipvl_port *port)
135a190d04dSMahesh Bandewar {
136a190d04dSMahesh Bandewar 	port->flags &= ~IPVLAN_F_PRIVATE;
137a190d04dSMahesh Bandewar }
138a190d04dSMahesh Bandewar 
ipvlan_is_vepa(const struct ipvl_port * port)139fe89aa6bSMahesh Bandewar static inline bool ipvlan_is_vepa(const struct ipvl_port *port)
140fe89aa6bSMahesh Bandewar {
141fe89aa6bSMahesh Bandewar 	return !!(port->flags & IPVLAN_F_VEPA);
142fe89aa6bSMahesh Bandewar }
143fe89aa6bSMahesh Bandewar 
ipvlan_mark_vepa(struct ipvl_port * port)144fe89aa6bSMahesh Bandewar static inline void ipvlan_mark_vepa(struct ipvl_port *port)
145fe89aa6bSMahesh Bandewar {
146fe89aa6bSMahesh Bandewar 	port->flags |= IPVLAN_F_VEPA;
147fe89aa6bSMahesh Bandewar }
148fe89aa6bSMahesh Bandewar 
ipvlan_clear_vepa(struct ipvl_port * port)149fe89aa6bSMahesh Bandewar static inline void ipvlan_clear_vepa(struct ipvl_port *port)
150fe89aa6bSMahesh Bandewar {
151fe89aa6bSMahesh Bandewar 	port->flags &= ~IPVLAN_F_VEPA;
152fe89aa6bSMahesh Bandewar }
153fe89aa6bSMahesh Bandewar 
1542ad7bf36SMahesh Bandewar void ipvlan_init_secret(void);
1552ad7bf36SMahesh Bandewar unsigned int ipvlan_mac_hash(const unsigned char *addr);
1562ad7bf36SMahesh Bandewar rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb);
157ba35f858SMahesh Bandewar void ipvlan_process_multicast(struct work_struct *work);
1582ad7bf36SMahesh Bandewar int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev);
1592ad7bf36SMahesh Bandewar void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr);
160e9997c29SJiri Benc struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
161e9997c29SJiri Benc 				   const void *iaddr, bool is_v6);
162e9997c29SJiri Benc bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6);
1636640e673SKonstantin Khlebnikov void ipvlan_ht_addr_del(struct ipvl_addr *addr);
164c675e06aSDaniel Borkmann struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
165c675e06aSDaniel Borkmann 				     int addr_type, bool use_dest);
166c675e06aSDaniel Borkmann void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type);
167235a9d89SSainath Grandhi void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
168235a9d89SSainath Grandhi 		     unsigned int len, bool success, bool mcast);
169235a9d89SSainath Grandhi int ipvlan_link_new(struct net *src_net, struct net_device *dev,
1707a3f4a18SMatthias Schiffer 		    struct nlattr *tb[], struct nlattr *data[],
1717a3f4a18SMatthias Schiffer 		    struct netlink_ext_ack *extack);
172235a9d89SSainath Grandhi void ipvlan_link_delete(struct net_device *dev, struct list_head *head);
173235a9d89SSainath Grandhi void ipvlan_link_setup(struct net_device *dev);
174235a9d89SSainath Grandhi int ipvlan_link_register(struct rtnl_link_ops *ops);
175c675e06aSDaniel Borkmann #ifdef CONFIG_IPVLAN_L3S
176c675e06aSDaniel Borkmann int ipvlan_l3s_register(struct ipvl_port *port);
177c675e06aSDaniel Borkmann void ipvlan_l3s_unregister(struct ipvl_port *port);
178c675e06aSDaniel Borkmann void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet);
179c675e06aSDaniel Borkmann int ipvlan_l3s_init(void);
180c675e06aSDaniel Borkmann void ipvlan_l3s_cleanup(void);
181c675e06aSDaniel Borkmann #else
ipvlan_l3s_register(struct ipvl_port * port)182c675e06aSDaniel Borkmann static inline int ipvlan_l3s_register(struct ipvl_port *port)
183c675e06aSDaniel Borkmann {
184c675e06aSDaniel Borkmann 	return -ENOTSUPP;
185c675e06aSDaniel Borkmann }
186c675e06aSDaniel Borkmann 
ipvlan_l3s_unregister(struct ipvl_port * port)187c675e06aSDaniel Borkmann static inline void ipvlan_l3s_unregister(struct ipvl_port *port)
188c675e06aSDaniel Borkmann {
189c675e06aSDaniel Borkmann }
190c675e06aSDaniel Borkmann 
ipvlan_migrate_l3s_hook(struct net * oldnet,struct net * newnet)191c675e06aSDaniel Borkmann static inline void ipvlan_migrate_l3s_hook(struct net *oldnet,
192c675e06aSDaniel Borkmann 					   struct net *newnet)
193c675e06aSDaniel Borkmann {
194c675e06aSDaniel Borkmann }
195c675e06aSDaniel Borkmann 
ipvlan_l3s_init(void)196c675e06aSDaniel Borkmann static inline int ipvlan_l3s_init(void)
197c675e06aSDaniel Borkmann {
198c675e06aSDaniel Borkmann 	return 0;
199c675e06aSDaniel Borkmann }
200c675e06aSDaniel Borkmann 
ipvlan_l3s_cleanup(void)201c675e06aSDaniel Borkmann static inline void ipvlan_l3s_cleanup(void)
202c675e06aSDaniel Borkmann {
203c675e06aSDaniel Borkmann }
204c675e06aSDaniel Borkmann #endif /* CONFIG_IPVLAN_L3S */
2051ec54cb4SPaolo Abeni 
netif_is_ipvlan_port(const struct net_device * dev)2061ec54cb4SPaolo Abeni static inline bool netif_is_ipvlan_port(const struct net_device *dev)
2071ec54cb4SPaolo Abeni {
208ae5799dcSPaolo Abeni 	return rcu_access_pointer(dev->rx_handler) == ipvlan_handle_frame;
2091ec54cb4SPaolo Abeni }
2101ec54cb4SPaolo Abeni 
2112ad7bf36SMahesh Bandewar #endif /* __IPVLAN_H */
212