aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/vxlan.c91
-rw-r--r--include/net/vxlan.h8
2 files changed, 62 insertions, 37 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index aab927b92fb3..f3496e995302 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1082,11 +1082,8 @@ static void vxlan_sock_put(struct sk_buff *skb)
1082} 1082}
1083 1083
1084/* On transmit, associate with the tunnel socket */ 1084/* On transmit, associate with the tunnel socket */
1085static void vxlan_set_owner(struct net_device *dev, struct sk_buff *skb) 1085static void vxlan_set_owner(struct sock *sk, struct sk_buff *skb)
1086{ 1086{
1087 struct vxlan_dev *vxlan = netdev_priv(dev);
1088 struct sock *sk = vxlan->vn_sock->sock->sk;
1089
1090 skb_orphan(skb); 1087 skb_orphan(skb);
1091 sock_hold(sk); 1088 sock_hold(sk);
1092 skb->sk = sk; 1089 skb->sk = sk;
@@ -1098,9 +1095,9 @@ static void vxlan_set_owner(struct net_device *dev, struct sk_buff *skb)
1098 * better and maybe available from hardware 1095 * better and maybe available from hardware
1099 * secondary choice is to use jhash on the Ethernet header 1096 * secondary choice is to use jhash on the Ethernet header
1100 */ 1097 */
1101static __be16 vxlan_src_port(const struct vxlan_dev *vxlan, struct sk_buff *skb) 1098__be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb)
1102{ 1099{
1103 unsigned int range = (vxlan->port_max - vxlan->port_min) + 1; 1100 unsigned int range = (port_max - port_min) + 1;
1104 u32 hash; 1101 u32 hash;
1105 1102
1106 hash = skb_get_rxhash(skb); 1103 hash = skb_get_rxhash(skb);
@@ -1108,8 +1105,9 @@ static __be16 vxlan_src_port(const struct vxlan_dev *vxlan, struct sk_buff *skb)
1108 hash = jhash(skb->data, 2 * ETH_ALEN, 1105 hash = jhash(skb->data, 2 * ETH_ALEN,
1109 (__force u32) skb->protocol); 1106 (__force u32) skb->protocol);
1110 1107
1111 return htons((((u64) hash * range) >> 32) + vxlan->port_min); 1108 return htons((((u64) hash * range) >> 32) + port_min);
1112} 1109}
1110EXPORT_SYMBOL_GPL(vxlan_src_port);
1113 1111
1114static int handle_offloads(struct sk_buff *skb) 1112static int handle_offloads(struct sk_buff *skb)
1115{ 1113{
@@ -1125,6 +1123,45 @@ static int handle_offloads(struct sk_buff *skb)
1125 return 0; 1123 return 0;
1126} 1124}
1127 1125
1126int vxlan_xmit_skb(struct net *net, struct vxlan_sock *vs,
1127 struct rtable *rt, struct sk_buff *skb,
1128 __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
1129 __be16 src_port, __be16 dst_port, __be32 vni)
1130{
1131 struct vxlanhdr *vxh;
1132 struct udphdr *uh;
1133 int err;
1134
1135 if (!skb->encapsulation) {
1136 skb_reset_inner_headers(skb);
1137 skb->encapsulation = 1;
1138 }
1139
1140 vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
1141 vxh->vx_flags = htonl(VXLAN_FLAGS);
1142 vxh->vx_vni = vni;
1143
1144 __skb_push(skb, sizeof(*uh));
1145 skb_reset_transport_header(skb);
1146 uh = udp_hdr(skb);
1147
1148 uh->dest = dst_port;
1149 uh->source = src_port;
1150
1151 uh->len = htons(skb->len);
1152 uh->check = 0;
1153
1154 vxlan_set_owner(vs->sock->sk, skb);
1155
1156 err = handle_offloads(skb);
1157 if (err)
1158 return err;
1159
1160 return iptunnel_xmit(net, rt, skb, src, dst,
1161 IPPROTO_UDP, tos, ttl, df);
1162}
1163EXPORT_SYMBOL_GPL(vxlan_xmit_skb);
1164
1128/* Bypass encapsulation if the destination is local */ 1165/* Bypass encapsulation if the destination is local */
1129static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, 1166static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
1130 struct vxlan_dev *dst_vxlan) 1167 struct vxlan_dev *dst_vxlan)
@@ -1162,8 +1199,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
1162 struct vxlan_dev *vxlan = netdev_priv(dev); 1199 struct vxlan_dev *vxlan = netdev_priv(dev);
1163 struct rtable *rt; 1200 struct rtable *rt;
1164 const struct iphdr *old_iph; 1201 const struct iphdr *old_iph;
1165 struct vxlanhdr *vxh;
1166 struct udphdr *uh;
1167 struct flowi4 fl4; 1202 struct flowi4 fl4;
1168 __be32 dst; 1203 __be32 dst;
1169 __be16 src_port, dst_port; 1204 __be16 src_port, dst_port;
@@ -1185,11 +1220,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
1185 goto drop; 1220 goto drop;
1186 } 1221 }
1187 1222
1188 if (!skb->encapsulation) {
1189 skb_reset_inner_headers(skb);
1190 skb->encapsulation = 1;
1191 }
1192
1193 /* Need space for new headers (invalidates iph ptr) */ 1223 /* Need space for new headers (invalidates iph ptr) */
1194 if (skb_cow_head(skb, VXLAN_HEADROOM)) 1224 if (skb_cow_head(skb, VXLAN_HEADROOM))
1195 goto drop; 1225 goto drop;
@@ -1204,7 +1234,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
1204 if (tos == 1) 1234 if (tos == 1)
1205 tos = ip_tunnel_get_dsfield(old_iph, skb); 1235 tos = ip_tunnel_get_dsfield(old_iph, skb);
1206 1236
1207 src_port = vxlan_src_port(vxlan, skb); 1237 src_port = vxlan_src_port(vxlan->port_min, vxlan->port_max, skb);
1208 1238
1209 memset(&fl4, 0, sizeof(fl4)); 1239 memset(&fl4, 0, sizeof(fl4));
1210 fl4.flowi4_oif = rdst->remote_ifindex; 1240 fl4.flowi4_oif = rdst->remote_ifindex;
@@ -1221,9 +1251,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
1221 1251
1222 if (rt->dst.dev == dev) { 1252 if (rt->dst.dev == dev) {
1223 netdev_dbg(dev, "circular route to %pI4\n", &dst); 1253 netdev_dbg(dev, "circular route to %pI4\n", &dst);
1224 ip_rt_put(rt);
1225 dev->stats.collisions++; 1254 dev->stats.collisions++;
1226 goto tx_error; 1255 goto rt_tx_error;
1227 } 1256 }
1228 1257
1229 /* Bypass encapsulation if the destination is local */ 1258 /* Bypass encapsulation if the destination is local */
@@ -1238,30 +1267,16 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
1238 vxlan_encap_bypass(skb, vxlan, dst_vxlan); 1267 vxlan_encap_bypass(skb, vxlan, dst_vxlan);
1239 return; 1268 return;
1240 } 1269 }
1241 vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
1242 vxh->vx_flags = htonl(VXLAN_FLAGS);
1243 vxh->vx_vni = htonl(vni << 8);
1244
1245 __skb_push(skb, sizeof(*uh));
1246 skb_reset_transport_header(skb);
1247 uh = udp_hdr(skb);
1248
1249 uh->dest = dst_port;
1250 uh->source = src_port;
1251
1252 uh->len = htons(skb->len);
1253 uh->check = 0;
1254
1255 vxlan_set_owner(dev, skb);
1256
1257 if (handle_offloads(skb))
1258 goto drop;
1259 1270
1260 tos = ip_tunnel_ecn_encap(tos, old_iph, skb); 1271 tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
1261 ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); 1272 ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
1262 1273
1263 err = iptunnel_xmit(dev_net(dev), rt, skb, fl4.saddr, dst, 1274 err = vxlan_xmit_skb(dev_net(dev), vxlan->vn_sock, rt, skb,
1264 IPPROTO_UDP, tos, ttl, df); 1275 fl4.saddr, dst, tos, ttl, df,
1276 src_port, dst_port, htonl(vni << 8));
1277
1278 if (err < 0)
1279 goto rt_tx_error;
1265 iptunnel_xmit_stats(err, &dev->stats, dev->tstats); 1280 iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
1266 1281
1267 return; 1282 return;
@@ -1270,6 +1285,8 @@ drop:
1270 dev->stats.tx_dropped++; 1285 dev->stats.tx_dropped++;
1271 goto tx_free; 1286 goto tx_free;
1272 1287
1288rt_tx_error:
1289 ip_rt_put(rt);
1273tx_error: 1290tx_error:
1274 dev->stats.tx_errors++; 1291 dev->stats.tx_errors++;
1275tx_free: 1292tx_free:
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 43de27585cb0..ad342e3688a0 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -28,4 +28,12 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
28 bool no_share); 28 bool no_share);
29 29
30void vxlan_sock_release(struct vxlan_sock *vs); 30void vxlan_sock_release(struct vxlan_sock *vs);
31
32int vxlan_xmit_skb(struct net *net, struct vxlan_sock *vs,
33 struct rtable *rt, struct sk_buff *skb,
34 __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
35 __be16 src_port, __be16 dst_port, __be32 vni);
36
37__be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb);
38
31#endif 39#endif