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 struct vxlan_fdb_key { 28 u8 eth_addr[ETH_ALEN]; 29 __be32 vni; 30 }; 31 32 /* Forwarding table entry */ 33 struct 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 */ 51 static 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 */ 57 static 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. 65 * Guaranteed to be non-NULL because remotes are never deleted. 66 */ 67 static inline struct vxlan_rdst *first_remote_rcu(struct vxlan_fdb *fdb) 68 { 69 if (rcu_access_pointer(fdb->nh)) 70 return NULL; 71 return list_entry_rcu(fdb->remotes.next, struct vxlan_rdst, list); 72 } 73 74 static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb) 75 { 76 if (rcu_access_pointer(fdb->nh)) 77 return NULL; 78 return list_first_entry(&fdb->remotes, struct vxlan_rdst, list); 79 } 80 81 #if IS_ENABLED(CONFIG_IPV6) 82 static inline 83 bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b) 84 { 85 if (a->sa.sa_family != b->sa.sa_family) 86 return false; 87 if (a->sa.sa_family == AF_INET6) 88 return ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr); 89 else 90 return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; 91 } 92 93 static inline int vxlan_nla_get_addr(union vxlan_addr *ip, 94 const struct nlattr *nla) 95 { 96 if (nla_len(nla) >= sizeof(struct in6_addr)) { 97 ip->sin6.sin6_addr = nla_get_in6_addr(nla); 98 ip->sa.sa_family = AF_INET6; 99 return 0; 100 } else if (nla_len(nla) >= sizeof(__be32)) { 101 ip->sin.sin_addr.s_addr = nla_get_in_addr(nla); 102 ip->sa.sa_family = AF_INET; 103 return 0; 104 } else { 105 return -EAFNOSUPPORT; 106 } 107 } 108 109 static inline int vxlan_nla_put_addr(struct sk_buff *skb, int attr, 110 const union vxlan_addr *ip) 111 { 112 if (ip->sa.sa_family == AF_INET6) 113 return nla_put_in6_addr(skb, attr, &ip->sin6.sin6_addr); 114 else 115 return nla_put_in_addr(skb, attr, ip->sin.sin_addr.s_addr); 116 } 117 118 static inline bool vxlan_addr_is_multicast(const union vxlan_addr *ip) 119 { 120 if (ip->sa.sa_family == AF_INET6) 121 return ipv6_addr_is_multicast(&ip->sin6.sin6_addr); 122 else 123 return ipv4_is_multicast(ip->sin.sin_addr.s_addr); 124 } 125 126 #else /* !CONFIG_IPV6 */ 127 128 static inline 129 bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b) 130 { 131 return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; 132 } 133 134 static inline int vxlan_nla_get_addr(union vxlan_addr *ip, 135 const struct nlattr *nla) 136 { 137 if (nla_len(nla) >= sizeof(struct in6_addr)) { 138 return -EAFNOSUPPORT; 139 } else if (nla_len(nla) >= sizeof(__be32)) { 140 ip->sin.sin_addr.s_addr = nla_get_in_addr(nla); 141 ip->sa.sa_family = AF_INET; 142 return 0; 143 } else { 144 return -EAFNOSUPPORT; 145 } 146 } 147 148 static inline int vxlan_nla_put_addr(struct sk_buff *skb, int attr, 149 const union vxlan_addr *ip) 150 { 151 return nla_put_in_addr(skb, attr, ip->sin.sin_addr.s_addr); 152 } 153 154 static inline bool vxlan_addr_is_multicast(const union vxlan_addr *ip) 155 { 156 return ipv4_is_multicast(ip->sin.sin_addr.s_addr); 157 } 158 159 #endif 160 161 static inline size_t vxlan_addr_size(const union vxlan_addr *ip) 162 { 163 if (ip->sa.sa_family == AF_INET6) 164 return sizeof(struct in6_addr); 165 else 166 return sizeof(__be32); 167 } 168 169 static inline struct vxlan_vni_node * 170 vxlan_vnifilter_lookup(struct vxlan_dev *vxlan, __be32 vni) 171 { 172 struct vxlan_vni_group *vg; 173 174 vg = rcu_dereference_rtnl(vxlan->vnigrp); 175 if (!vg) 176 return NULL; 177 178 return rhashtable_lookup_fast(&vg->vni_hash, &vni, 179 vxlan_vni_rht_params); 180 } 181 182 /* vxlan_core.c */ 183 int vxlan_fdb_create(struct vxlan_dev *vxlan, 184 const u8 *mac, union vxlan_addr *ip, 185 __u16 state, __be16 port, __be32 src_vni, 186 __be32 vni, __u32 ifindex, __u16 ndm_flags, 187 u32 nhid, struct vxlan_fdb **fdb, 188 struct netlink_ext_ack *extack); 189 int __vxlan_fdb_delete(struct vxlan_dev *vxlan, 190 const unsigned char *addr, union vxlan_addr ip, 191 __be16 port, __be32 src_vni, __be32 vni, 192 u32 ifindex, bool swdev_notify); 193 u32 eth_vni_hash(const unsigned char *addr, __be32 vni); 194 u32 fdb_head_index(struct vxlan_dev *vxlan, const u8 *mac, __be32 vni); 195 int vxlan_fdb_update(struct vxlan_dev *vxlan, 196 const u8 *mac, union vxlan_addr *ip, 197 __u16 state, __u16 flags, 198 __be16 port, __be32 src_vni, __be32 vni, 199 __u32 ifindex, __u16 ndm_flags, u32 nhid, 200 bool swdev_notify, struct netlink_ext_ack *extack); 201 void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, 202 __be32 default_vni, struct vxlan_rdst *rdst, bool did_rsc); 203 int vxlan_vni_in_use(struct net *src_net, struct vxlan_dev *vxlan, 204 struct vxlan_config *conf, __be32 vni); 205 206 /* vxlan_vnifilter.c */ 207 int vxlan_vnigroup_init(struct vxlan_dev *vxlan); 208 void vxlan_vnigroup_uninit(struct vxlan_dev *vxlan); 209 210 int vxlan_vnifilter_init(void); 211 void vxlan_vnifilter_uninit(void); 212 void vxlan_vnifilter_count(struct vxlan_dev *vxlan, __be32 vni, 213 struct vxlan_vni_node *vninode, 214 int type, unsigned int len); 215 216 void vxlan_vs_add_vnigrp(struct vxlan_dev *vxlan, 217 struct vxlan_sock *vs, 218 bool ipv6); 219 void vxlan_vs_del_vnigrp(struct vxlan_dev *vxlan); 220 int vxlan_vnilist_update_group(struct vxlan_dev *vxlan, 221 union vxlan_addr *old_remote_ip, 222 union vxlan_addr *new_remote_ip, 223 struct netlink_ext_ack *extack); 224 225 226 /* vxlan_multicast.c */ 227 int vxlan_multicast_join(struct vxlan_dev *vxlan); 228 int vxlan_multicast_leave(struct vxlan_dev *vxlan); 229 bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev, 230 __be32 vni, union vxlan_addr *rip, int rifindex); 231 int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip, 232 int rifindex); 233 int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip, 234 int rifindex); 235 236 /* vxlan_mdb.c */ 237 int vxlan_mdb_dump(struct net_device *dev, struct sk_buff *skb, 238 struct netlink_callback *cb); 239 int vxlan_mdb_add(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags, 240 struct netlink_ext_ack *extack); 241 int vxlan_mdb_del(struct net_device *dev, struct nlattr *tb[], 242 struct netlink_ext_ack *extack); 243 int vxlan_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[], 244 struct netlink_ext_ack *extack); 245 int vxlan_mdb_get(struct net_device *dev, struct nlattr *tb[], u32 portid, 246 u32 seq, struct netlink_ext_ack *extack); 247 struct vxlan_mdb_entry *vxlan_mdb_entry_skb_get(struct vxlan_dev *vxlan, 248 struct sk_buff *skb, 249 __be32 src_vni); 250 netdev_tx_t vxlan_mdb_xmit(struct vxlan_dev *vxlan, 251 const struct vxlan_mdb_entry *mdb_entry, 252 struct sk_buff *skb); 253 int vxlan_mdb_init(struct vxlan_dev *vxlan); 254 void vxlan_mdb_fini(struct vxlan_dev *vxlan); 255 #endif 256