162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#ifndef __IPVLAN_H
662306a36Sopenharmony_ci#define __IPVLAN_H
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/kernel.h>
962306a36Sopenharmony_ci#include <linux/types.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/init.h>
1262306a36Sopenharmony_ci#include <linux/rculist.h>
1362306a36Sopenharmony_ci#include <linux/notifier.h>
1462306a36Sopenharmony_ci#include <linux/netdevice.h>
1562306a36Sopenharmony_ci#include <linux/etherdevice.h>
1662306a36Sopenharmony_ci#include <linux/if_arp.h>
1762306a36Sopenharmony_ci#include <linux/if_link.h>
1862306a36Sopenharmony_ci#include <linux/if_vlan.h>
1962306a36Sopenharmony_ci#include <linux/ip.h>
2062306a36Sopenharmony_ci#include <linux/inetdevice.h>
2162306a36Sopenharmony_ci#include <linux/netfilter.h>
2262306a36Sopenharmony_ci#include <net/ip.h>
2362306a36Sopenharmony_ci#include <net/ip6_route.h>
2462306a36Sopenharmony_ci#include <net/netns/generic.h>
2562306a36Sopenharmony_ci#include <net/rtnetlink.h>
2662306a36Sopenharmony_ci#include <net/route.h>
2762306a36Sopenharmony_ci#include <net/addrconf.h>
2862306a36Sopenharmony_ci#include <net/l3mdev.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define IPVLAN_DRV	"ipvlan"
3162306a36Sopenharmony_ci#define IPV_DRV_VER	"0.1"
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define IPVLAN_HASH_SIZE	(1 << BITS_PER_BYTE)
3462306a36Sopenharmony_ci#define IPVLAN_HASH_MASK	(IPVLAN_HASH_SIZE - 1)
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define IPVLAN_MAC_FILTER_BITS	8
3762306a36Sopenharmony_ci#define IPVLAN_MAC_FILTER_SIZE	(1 << IPVLAN_MAC_FILTER_BITS)
3862306a36Sopenharmony_ci#define IPVLAN_MAC_FILTER_MASK	(IPVLAN_MAC_FILTER_SIZE - 1)
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define IPVLAN_QBACKLOG_LIMIT	1000
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_citypedef enum {
4362306a36Sopenharmony_ci	IPVL_IPV6 = 0,
4462306a36Sopenharmony_ci	IPVL_ICMPV6,
4562306a36Sopenharmony_ci	IPVL_IPV4,
4662306a36Sopenharmony_ci	IPVL_ARP,
4762306a36Sopenharmony_ci} ipvl_hdr_type;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistruct ipvl_pcpu_stats {
5062306a36Sopenharmony_ci	u64_stats_t		rx_pkts;
5162306a36Sopenharmony_ci	u64_stats_t		rx_bytes;
5262306a36Sopenharmony_ci	u64_stats_t		rx_mcast;
5362306a36Sopenharmony_ci	u64_stats_t		tx_pkts;
5462306a36Sopenharmony_ci	u64_stats_t		tx_bytes;
5562306a36Sopenharmony_ci	struct u64_stats_sync	syncp;
5662306a36Sopenharmony_ci	u32			rx_errs;
5762306a36Sopenharmony_ci	u32			tx_drps;
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistruct ipvl_port;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistruct ipvl_dev {
6362306a36Sopenharmony_ci	struct net_device	*dev;
6462306a36Sopenharmony_ci	struct list_head	pnode;
6562306a36Sopenharmony_ci	struct ipvl_port	*port;
6662306a36Sopenharmony_ci	struct net_device	*phy_dev;
6762306a36Sopenharmony_ci	struct list_head	addrs;
6862306a36Sopenharmony_ci	struct ipvl_pcpu_stats	__percpu *pcpu_stats;
6962306a36Sopenharmony_ci	DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE);
7062306a36Sopenharmony_ci	netdev_features_t	sfeatures;
7162306a36Sopenharmony_ci	u32			msg_enable;
7262306a36Sopenharmony_ci	spinlock_t		addrs_lock;
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistruct ipvl_addr {
7662306a36Sopenharmony_ci	struct ipvl_dev		*master; /* Back pointer to master */
7762306a36Sopenharmony_ci	union {
7862306a36Sopenharmony_ci		struct in6_addr	ip6;	 /* IPv6 address on logical interface */
7962306a36Sopenharmony_ci		struct in_addr	ip4;	 /* IPv4 address on logical interface */
8062306a36Sopenharmony_ci	} ipu;
8162306a36Sopenharmony_ci#define ip6addr	ipu.ip6
8262306a36Sopenharmony_ci#define ip4addr ipu.ip4
8362306a36Sopenharmony_ci	struct hlist_node	hlnode;  /* Hash-table linkage */
8462306a36Sopenharmony_ci	struct list_head	anode;   /* logical-interface linkage */
8562306a36Sopenharmony_ci	ipvl_hdr_type		atype;
8662306a36Sopenharmony_ci	struct rcu_head		rcu;
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistruct ipvl_port {
9062306a36Sopenharmony_ci	struct net_device	*dev;
9162306a36Sopenharmony_ci	possible_net_t		pnet;
9262306a36Sopenharmony_ci	struct hlist_head	hlhead[IPVLAN_HASH_SIZE];
9362306a36Sopenharmony_ci	struct list_head	ipvlans;
9462306a36Sopenharmony_ci	u16			mode;
9562306a36Sopenharmony_ci	u16			flags;
9662306a36Sopenharmony_ci	u16			dev_id_start;
9762306a36Sopenharmony_ci	struct work_struct	wq;
9862306a36Sopenharmony_ci	struct sk_buff_head	backlog;
9962306a36Sopenharmony_ci	int			count;
10062306a36Sopenharmony_ci	struct ida		ida;
10162306a36Sopenharmony_ci	netdevice_tracker	dev_tracker;
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistruct ipvl_skb_cb {
10562306a36Sopenharmony_ci	bool tx_pkt;
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci#define IPVL_SKB_CB(_skb) ((struct ipvl_skb_cb *)&((_skb)->cb[0]))
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic inline struct ipvl_port *ipvlan_port_get_rcu(const struct net_device *d)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	return rcu_dereference(d->rx_handler_data);
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistatic inline struct ipvl_port *ipvlan_port_get_rcu_bh(const struct net_device *d)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	return rcu_dereference_bh(d->rx_handler_data);
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic inline struct ipvl_port *ipvlan_port_get_rtnl(const struct net_device *d)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	return rtnl_dereference(d->rx_handler_data);
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic inline bool ipvlan_is_private(const struct ipvl_port *port)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	return !!(port->flags & IPVLAN_F_PRIVATE);
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic inline void ipvlan_mark_private(struct ipvl_port *port)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	port->flags |= IPVLAN_F_PRIVATE;
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic inline void ipvlan_clear_private(struct ipvl_port *port)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	port->flags &= ~IPVLAN_F_PRIVATE;
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic inline bool ipvlan_is_vepa(const struct ipvl_port *port)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	return !!(port->flags & IPVLAN_F_VEPA);
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic inline void ipvlan_mark_vepa(struct ipvl_port *port)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	port->flags |= IPVLAN_F_VEPA;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic inline void ipvlan_clear_vepa(struct ipvl_port *port)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	port->flags &= ~IPVLAN_F_VEPA;
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_civoid ipvlan_init_secret(void);
15562306a36Sopenharmony_ciunsigned int ipvlan_mac_hash(const unsigned char *addr);
15662306a36Sopenharmony_cirx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb);
15762306a36Sopenharmony_civoid ipvlan_process_multicast(struct work_struct *work);
15862306a36Sopenharmony_ciint ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev);
15962306a36Sopenharmony_civoid ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr);
16062306a36Sopenharmony_cistruct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
16162306a36Sopenharmony_ci				   const void *iaddr, bool is_v6);
16262306a36Sopenharmony_cibool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6);
16362306a36Sopenharmony_civoid ipvlan_ht_addr_del(struct ipvl_addr *addr);
16462306a36Sopenharmony_cistruct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
16562306a36Sopenharmony_ci				     int addr_type, bool use_dest);
16662306a36Sopenharmony_civoid *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type);
16762306a36Sopenharmony_civoid ipvlan_count_rx(const struct ipvl_dev *ipvlan,
16862306a36Sopenharmony_ci		     unsigned int len, bool success, bool mcast);
16962306a36Sopenharmony_ciint ipvlan_link_new(struct net *src_net, struct net_device *dev,
17062306a36Sopenharmony_ci		    struct nlattr *tb[], struct nlattr *data[],
17162306a36Sopenharmony_ci		    struct netlink_ext_ack *extack);
17262306a36Sopenharmony_civoid ipvlan_link_delete(struct net_device *dev, struct list_head *head);
17362306a36Sopenharmony_civoid ipvlan_link_setup(struct net_device *dev);
17462306a36Sopenharmony_ciint ipvlan_link_register(struct rtnl_link_ops *ops);
17562306a36Sopenharmony_ci#ifdef CONFIG_IPVLAN_L3S
17662306a36Sopenharmony_ciint ipvlan_l3s_register(struct ipvl_port *port);
17762306a36Sopenharmony_civoid ipvlan_l3s_unregister(struct ipvl_port *port);
17862306a36Sopenharmony_civoid ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet);
17962306a36Sopenharmony_ciint ipvlan_l3s_init(void);
18062306a36Sopenharmony_civoid ipvlan_l3s_cleanup(void);
18162306a36Sopenharmony_ci#else
18262306a36Sopenharmony_cistatic inline int ipvlan_l3s_register(struct ipvl_port *port)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	return -ENOTSUPP;
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistatic inline void ipvlan_l3s_unregister(struct ipvl_port *port)
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic inline void ipvlan_migrate_l3s_hook(struct net *oldnet,
19262306a36Sopenharmony_ci					   struct net *newnet)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic inline int ipvlan_l3s_init(void)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	return 0;
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic inline void ipvlan_l3s_cleanup(void)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci#endif /* CONFIG_IPVLAN_L3S */
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic inline bool netif_is_ipvlan_port(const struct net_device *dev)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	return rcu_access_pointer(dev->rx_handler) == ipvlan_handle_frame;
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci#endif /* __IPVLAN_H */
212