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