Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Vxlan private header file
4 *
5 */
6
7#ifndef _VXLAN_PRIVATE_H
8#define _VXLAN_PRIVATE_H
9
10#include <linux/rhashtable.h>
11
12extern unsigned int vxlan_net_id;
13extern const u8 all_zeros_mac[ETH_ALEN + 2];
14extern const struct rhashtable_params vxlan_vni_rht_params;
15
16#define PORT_HASH_BITS 8
17#define PORT_HASH_SIZE (1 << PORT_HASH_BITS)
18
19/* per-network namespace private data for this module */
20struct vxlan_net {
21 struct list_head vxlan_list;
22 /* sock_list is protected by rtnl lock */
23 struct hlist_head sock_list[PORT_HASH_SIZE];
24 struct notifier_block nexthop_notifier_block;
25};
26
27struct vxlan_fdb_key {
28 u8 eth_addr[ETH_ALEN];
29 __be32 vni;
30};
31
32/* Forwarding table entry */
33struct vxlan_fdb {
34 struct rhash_head rhnode;
35 struct rcu_head rcu;
36 unsigned long updated; /* jiffies */
37 unsigned long used;
38 struct list_head remotes;
39 struct vxlan_fdb_key key;
40 u16 state; /* see ndm_state */
41 u16 flags; /* see ndm_flags and below */
42 struct list_head nh_list;
43 struct hlist_node fdb_node;
44 struct nexthop __rcu *nh;
45 struct vxlan_dev __rcu *vdev;
46};
47
48#define NTF_VXLAN_ADDED_BY_USER 0x100
49
50/* Virtual Network hash table head */
51static inline struct hlist_head *vni_head(struct vxlan_sock *vs, __be32 vni)
52{
53 return &vs->vni_list[hash_32((__force u32)vni, VNI_HASH_BITS)];
54}
55
56/* Socket hash table head */
57static inline struct hlist_head *vs_head(struct net *net, __be16 port)
58{
59 struct vxlan_net *vn = net_generic(net, vxlan_net_id);
60
61 return &vn->sock_list[hash_32(ntohs(port), PORT_HASH_BITS)];
62}
63
64/* First remote destination for a forwarding entry. */
65static inline struct vxlan_rdst *first_remote_rcu(struct vxlan_fdb *fdb)
66{
67 if (rcu_access_pointer(fdb->nh))
68 return NULL;
69 return list_entry_rcu(fdb->remotes.next, struct vxlan_rdst, list);
70}
71
72static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
73{
74 if (rcu_access_pointer(fdb->nh))
75 return NULL;
76 return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
77}
78
79#if IS_ENABLED(CONFIG_IPV6)
80static inline
81bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b)
82{
83 if (a->sa.sa_family != b->sa.sa_family)
84 return false;
85 if (a->sa.sa_family == AF_INET6)
86 return ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr);
87 else
88 return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr;
89}
90
91static inline int vxlan_nla_get_addr(union vxlan_addr *ip,
92 const struct nlattr *nla)
93{
94 if (nla_len(nla) >= sizeof(struct in6_addr)) {
95 ip->sin6.sin6_addr = nla_get_in6_addr(nla);
96 ip->sa.sa_family = AF_INET6;
97 return 0;
98 } else if (nla_len(nla) >= sizeof(__be32)) {
99 ip->sin.sin_addr.s_addr = nla_get_in_addr(nla);
100 ip->sa.sa_family = AF_INET;
101 return 0;
102 } else {
103 return -EAFNOSUPPORT;
104 }
105}
106
107static inline int vxlan_nla_put_addr(struct sk_buff *skb, int attr,
108 const union vxlan_addr *ip)
109{
110 if (ip->sa.sa_family == AF_INET6)
111 return nla_put_in6_addr(skb, attr, &ip->sin6.sin6_addr);
112 else
113 return nla_put_in_addr(skb, attr, ip->sin.sin_addr.s_addr);
114}
115
116static inline bool vxlan_addr_is_multicast(const union vxlan_addr *ip)
117{
118 if (ip->sa.sa_family == AF_INET6)
119 return ipv6_addr_is_multicast(&ip->sin6.sin6_addr);
120 else
121 return ipv4_is_multicast(ip->sin.sin_addr.s_addr);
122}
123
124#else /* !CONFIG_IPV6 */
125
126static inline
127bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b)
128{
129 return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr;
130}
131
132static inline int vxlan_nla_get_addr(union vxlan_addr *ip,
133 const struct nlattr *nla)
134{
135 if (nla_len(nla) >= sizeof(struct in6_addr)) {
136 return -EAFNOSUPPORT;
137 } else if (nla_len(nla) >= sizeof(__be32)) {
138 ip->sin.sin_addr.s_addr = nla_get_in_addr(nla);
139 ip->sa.sa_family = AF_INET;
140 return 0;
141 } else {
142 return -EAFNOSUPPORT;
143 }
144}
145
146static inline int vxlan_nla_put_addr(struct sk_buff *skb, int attr,
147 const union vxlan_addr *ip)
148{
149 return nla_put_in_addr(skb, attr, ip->sin.sin_addr.s_addr);
150}
151
152static inline bool vxlan_addr_is_multicast(const union vxlan_addr *ip)
153{
154 return ipv4_is_multicast(ip->sin.sin_addr.s_addr);
155}
156
157#endif
158
159static inline size_t vxlan_addr_size(const union vxlan_addr *ip)
160{
161 if (ip->sa.sa_family == AF_INET6)
162 return sizeof(struct in6_addr);
163 else
164 return sizeof(__be32);
165}
166
167static inline struct vxlan_vni_node *
168vxlan_vnifilter_lookup(struct vxlan_dev *vxlan, __be32 vni)
169{
170 struct vxlan_vni_group *vg;
171
172 vg = rcu_dereference_rtnl(vxlan->vnigrp);
173 if (!vg)
174 return NULL;
175
176 return rhashtable_lookup_fast(&vg->vni_hash, &vni,
177 vxlan_vni_rht_params);
178}
179
180/* vxlan_core.c */
181int vxlan_fdb_create(struct vxlan_dev *vxlan,
182 const u8 *mac, union vxlan_addr *ip,
183 __u16 state, __be16 port, __be32 src_vni,
184 __be32 vni, __u32 ifindex, __u16 ndm_flags,
185 u32 nhid, struct vxlan_fdb **fdb,
186 struct netlink_ext_ack *extack);
187int __vxlan_fdb_delete(struct vxlan_dev *vxlan,
188 const unsigned char *addr, union vxlan_addr ip,
189 __be16 port, __be32 src_vni, __be32 vni,
190 u32 ifindex, bool swdev_notify);
191int vxlan_fdb_update(struct vxlan_dev *vxlan,
192 const u8 *mac, union vxlan_addr *ip,
193 __u16 state, __u16 flags,
194 __be16 port, __be32 src_vni, __be32 vni,
195 __u32 ifindex, __u16 ndm_flags, u32 nhid,
196 bool swdev_notify, struct netlink_ext_ack *extack);
197void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
198 __be32 default_vni, struct vxlan_rdst *rdst, bool did_rsc);
199int vxlan_vni_in_use(struct net *src_net, struct vxlan_dev *vxlan,
200 struct vxlan_config *conf, __be32 vni);
201
202/* vxlan_vnifilter.c */
203int vxlan_vnigroup_init(struct vxlan_dev *vxlan);
204void vxlan_vnigroup_uninit(struct vxlan_dev *vxlan);
205
206int vxlan_vnifilter_init(void);
207void vxlan_vnifilter_uninit(void);
208void vxlan_vnifilter_count(struct vxlan_dev *vxlan, __be32 vni,
209 struct vxlan_vni_node *vninode,
210 int type, unsigned int len);
211
212void vxlan_vs_add_vnigrp(struct vxlan_dev *vxlan,
213 struct vxlan_sock *vs,
214 bool ipv6);
215void vxlan_vs_del_vnigrp(struct vxlan_dev *vxlan);
216int vxlan_vnilist_update_group(struct vxlan_dev *vxlan,
217 union vxlan_addr *old_remote_ip,
218 union vxlan_addr *new_remote_ip,
219 struct netlink_ext_ack *extack);
220
221
222/* vxlan_multicast.c */
223int vxlan_multicast_join(struct vxlan_dev *vxlan);
224int vxlan_multicast_leave(struct vxlan_dev *vxlan);
225bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev,
226 __be32 vni, union vxlan_addr *rip, int rifindex);
227int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip,
228 int rifindex);
229int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip,
230 int rifindex);
231
232/* vxlan_mdb.c */
233int vxlan_mdb_dump(struct net_device *dev, struct sk_buff *skb,
234 struct netlink_callback *cb);
235int vxlan_mdb_add(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags,
236 struct netlink_ext_ack *extack);
237int vxlan_mdb_del(struct net_device *dev, struct nlattr *tb[],
238 struct netlink_ext_ack *extack);
239int vxlan_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[],
240 struct netlink_ext_ack *extack);
241int vxlan_mdb_get(struct net_device *dev, struct nlattr *tb[], u32 portid,
242 u32 seq, struct netlink_ext_ack *extack);
243struct vxlan_mdb_entry *vxlan_mdb_entry_skb_get(struct vxlan_dev *vxlan,
244 struct sk_buff *skb,
245 __be32 src_vni);
246netdev_tx_t vxlan_mdb_xmit(struct vxlan_dev *vxlan,
247 const struct vxlan_mdb_entry *mdb_entry,
248 struct sk_buff *skb);
249int vxlan_mdb_init(struct vxlan_dev *vxlan);
250void vxlan_mdb_fini(struct vxlan_dev *vxlan);
251#endif