mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 21:35:07 +00:00
Merge branch 'vxlan-skb-drop-reasons'
Menglong Dong says: ==================== net: vxlan: add skb drop reasons support In this series, we add skb drop reasons support to VXLAN, and following new skb drop reasons are introduced: SKB_DROP_REASON_VXLAN_INVALID_HDR SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND SKB_DROP_REASON_VXLAN_ENTRY_EXISTS SKB_DROP_REASON_VXLAN_NO_REMOTE SKB_DROP_REASON_MAC_INVALID_SOURCE SKB_DROP_REASON_IP_TUNNEL_ECN SKB_DROP_REASON_TUNNEL_TXINFO SKB_DROP_REASON_LOCAL_MAC We add some helper functions in this series, who will capture the drop reasons from pskb_may_pull_reason and return them: pskb_network_may_pull_reason() pskb_inet_may_pull_reason() And we also make the following functions return skb drop reasons: skb_vlan_inet_prepare() vxlan_remcsum() vxlan_snoop() vxlan_set_mac() Changes since v6: - fix some typos in the document for SKB_DROP_REASON_TUNNEL_TXINFO Changes since v5: - fix some typos in the document for SKB_DROP_REASON_TUNNEL_TXINFO Changes since v4: - make skb_vlan_inet_prepare() return drop reasons, instead of introduce a wrapper for it in the 3rd patch. - modify the document for SKB_DROP_REASON_LOCAL_MAC and SKB_DROP_REASON_TUNNEL_TXINFO. Changes since v3: - rename SKB_DROP_REASON_VXLAN_INVALID_SMAC to SKB_DROP_REASON_MAC_INVALID_SOURCE in the 6th patch Changes since v2: - move all the drop reasons of VXLAN to the "core", instead of introducing the VXLAN drop reason subsystem - add the 6th patch, which capture the drop reasons from vxlan_snoop() - move the commits for vxlan_remcsum() and vxlan_set_mac() after vxlan_rcv() to update the call of them accordingly - fix some format problems Changes since v1: - document all the drop reasons that we introduce - rename the drop reasons to make them more descriptive, as Ido advised - remove the 2nd patch, which introduce the SKB_DR_RESET - add the 4th patch, which adds skb_vlan_inet_prepare_reason() helper - introduce the 6th patch, which make vxlan_set_mac return drop reasons - introduce the 10th patch, which uses VXLAN_DROP_NO_REMOTE as the drop reasons, as Ido advised ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
eae38f09cc
@ -317,7 +317,7 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
__be32 saddr;
|
||||
int err;
|
||||
|
||||
if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
|
||||
if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!sock)
|
||||
@ -387,7 +387,7 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
__be16 sport;
|
||||
int err;
|
||||
|
||||
if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
|
||||
if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!sock)
|
||||
|
@ -827,7 +827,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
__be16 sport;
|
||||
int err;
|
||||
|
||||
if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
|
||||
if (skb_vlan_inet_prepare(skb, inner_proto_inherit))
|
||||
return -EINVAL;
|
||||
|
||||
if (!gs4)
|
||||
@ -937,7 +937,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
__be16 sport;
|
||||
int err;
|
||||
|
||||
if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
|
||||
if (skb_vlan_inet_prepare(skb, inner_proto_inherit))
|
||||
return -EINVAL;
|
||||
|
||||
if (!gs6)
|
||||
|
@ -1437,9 +1437,10 @@ errout:
|
||||
* and Tunnel endpoint.
|
||||
* Return true if packet is bogus and should be dropped.
|
||||
*/
|
||||
static bool vxlan_snoop(struct net_device *dev,
|
||||
union vxlan_addr *src_ip, const u8 *src_mac,
|
||||
u32 src_ifindex, __be32 vni)
|
||||
static enum skb_drop_reason vxlan_snoop(struct net_device *dev,
|
||||
union vxlan_addr *src_ip,
|
||||
const u8 *src_mac, u32 src_ifindex,
|
||||
__be32 vni)
|
||||
{
|
||||
struct vxlan_dev *vxlan = netdev_priv(dev);
|
||||
struct vxlan_fdb *f;
|
||||
@ -1447,7 +1448,7 @@ static bool vxlan_snoop(struct net_device *dev,
|
||||
|
||||
/* Ignore packets from invalid src-address */
|
||||
if (!is_valid_ether_addr(src_mac))
|
||||
return true;
|
||||
return SKB_DROP_REASON_MAC_INVALID_SOURCE;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (src_ip->sa.sa_family == AF_INET6 &&
|
||||
@ -1461,15 +1462,15 @@ static bool vxlan_snoop(struct net_device *dev,
|
||||
|
||||
if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip) &&
|
||||
rdst->remote_ifindex == ifindex))
|
||||
return false;
|
||||
return SKB_NOT_DROPPED_YET;
|
||||
|
||||
/* Don't migrate static entries, drop packets */
|
||||
if (f->state & (NUD_PERMANENT | NUD_NOARP))
|
||||
return true;
|
||||
return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS;
|
||||
|
||||
/* Don't override an fdb with nexthop with a learnt entry */
|
||||
if (rcu_access_pointer(f->nh))
|
||||
return true;
|
||||
return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS;
|
||||
|
||||
if (net_ratelimit())
|
||||
netdev_info(dev,
|
||||
@ -1497,7 +1498,7 @@ static bool vxlan_snoop(struct net_device *dev,
|
||||
spin_unlock(&vxlan->hash_lock[hash_index]);
|
||||
}
|
||||
|
||||
return false;
|
||||
return SKB_NOT_DROPPED_YET;
|
||||
}
|
||||
|
||||
static bool __vxlan_sock_release_prep(struct vxlan_sock *vs)
|
||||
@ -1551,9 +1552,11 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan)
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool vxlan_remcsum(struct vxlanhdr *unparsed,
|
||||
struct sk_buff *skb, u32 vxflags)
|
||||
static enum skb_drop_reason vxlan_remcsum(struct vxlanhdr *unparsed,
|
||||
struct sk_buff *skb,
|
||||
u32 vxflags)
|
||||
{
|
||||
enum skb_drop_reason reason;
|
||||
size_t start, offset;
|
||||
|
||||
if (!(unparsed->vx_flags & VXLAN_HF_RCO) || skb->remcsum_offload)
|
||||
@ -1562,15 +1565,17 @@ static bool vxlan_remcsum(struct vxlanhdr *unparsed,
|
||||
start = vxlan_rco_start(unparsed->vx_vni);
|
||||
offset = start + vxlan_rco_offset(unparsed->vx_vni);
|
||||
|
||||
if (!pskb_may_pull(skb, offset + sizeof(u16)))
|
||||
return false;
|
||||
reason = pskb_may_pull_reason(skb, offset + sizeof(u16));
|
||||
if (reason)
|
||||
return reason;
|
||||
|
||||
skb_remcsum_process(skb, (void *)(vxlan_hdr(skb) + 1), start, offset,
|
||||
!!(vxflags & VXLAN_F_REMCSUM_NOPARTIAL));
|
||||
out:
|
||||
unparsed->vx_flags &= ~VXLAN_HF_RCO;
|
||||
unparsed->vx_vni &= VXLAN_VNI_MASK;
|
||||
return true;
|
||||
|
||||
return SKB_NOT_DROPPED_YET;
|
||||
}
|
||||
|
||||
static void vxlan_parse_gbp_hdr(struct vxlanhdr *unparsed,
|
||||
@ -1604,9 +1609,9 @@ out:
|
||||
unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
|
||||
}
|
||||
|
||||
static bool vxlan_set_mac(struct vxlan_dev *vxlan,
|
||||
struct vxlan_sock *vs,
|
||||
struct sk_buff *skb, __be32 vni)
|
||||
static enum skb_drop_reason vxlan_set_mac(struct vxlan_dev *vxlan,
|
||||
struct vxlan_sock *vs,
|
||||
struct sk_buff *skb, __be32 vni)
|
||||
{
|
||||
union vxlan_addr saddr;
|
||||
u32 ifindex = skb->dev->ifindex;
|
||||
@ -1617,7 +1622,7 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
|
||||
|
||||
/* Ignore packet loops (and multicast echo) */
|
||||
if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
|
||||
return false;
|
||||
return SKB_DROP_REASON_LOCAL_MAC;
|
||||
|
||||
/* Get address from the outer IP header */
|
||||
if (vxlan_get_sk_family(vs) == AF_INET) {
|
||||
@ -1630,11 +1635,11 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((vxlan->cfg.flags & VXLAN_F_LEARN) &&
|
||||
vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source, ifindex, vni))
|
||||
return false;
|
||||
if (!(vxlan->cfg.flags & VXLAN_F_LEARN))
|
||||
return SKB_NOT_DROPPED_YET;
|
||||
|
||||
return true;
|
||||
return vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source,
|
||||
ifindex, vni);
|
||||
}
|
||||
|
||||
static bool vxlan_ecn_decapsulate(struct vxlan_sock *vs, void *oiph,
|
||||
@ -1671,13 +1676,15 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
struct vxlan_metadata _md;
|
||||
struct vxlan_metadata *md = &_md;
|
||||
__be16 protocol = htons(ETH_P_TEB);
|
||||
enum skb_drop_reason reason;
|
||||
bool raw_proto = false;
|
||||
void *oiph;
|
||||
__be32 vni = 0;
|
||||
int nh;
|
||||
|
||||
/* Need UDP and VXLAN header to be present */
|
||||
if (!pskb_may_pull(skb, VXLAN_HLEN))
|
||||
reason = pskb_may_pull_reason(skb, VXLAN_HLEN);
|
||||
if (reason)
|
||||
goto drop;
|
||||
|
||||
unparsed = *vxlan_hdr(skb);
|
||||
@ -1686,6 +1693,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
|
||||
ntohl(vxlan_hdr(skb)->vx_flags),
|
||||
ntohl(vxlan_hdr(skb)->vx_vni));
|
||||
reason = SKB_DROP_REASON_VXLAN_INVALID_HDR;
|
||||
/* Return non vxlan pkt */
|
||||
goto drop;
|
||||
}
|
||||
@ -1699,8 +1707,10 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
vni = vxlan_vni(vxlan_hdr(skb)->vx_vni);
|
||||
|
||||
vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni, &vninode);
|
||||
if (!vxlan)
|
||||
if (!vxlan) {
|
||||
reason = SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* For backwards compatibility, only allow reserved fields to be
|
||||
* used by VXLAN extensions if explicitly requested.
|
||||
@ -1713,12 +1723,16 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
if (__iptunnel_pull_header(skb, VXLAN_HLEN, protocol, raw_proto,
|
||||
!net_eq(vxlan->net, dev_net(vxlan->dev))))
|
||||
!net_eq(vxlan->net, dev_net(vxlan->dev)))) {
|
||||
reason = SKB_DROP_REASON_NOMEM;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (vs->flags & VXLAN_F_REMCSUM_RX)
|
||||
if (unlikely(!vxlan_remcsum(&unparsed, skb, vs->flags)))
|
||||
if (vs->flags & VXLAN_F_REMCSUM_RX) {
|
||||
reason = vxlan_remcsum(&unparsed, skb, vs->flags);
|
||||
if (unlikely(reason))
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (vxlan_collect_metadata(vs)) {
|
||||
IP_TUNNEL_DECLARE_FLAGS(flags) = { };
|
||||
@ -1728,8 +1742,10 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
tun_dst = udp_tun_rx_dst(skb, vxlan_get_sk_family(vs), flags,
|
||||
key32_to_tunnel_id(vni), sizeof(*md));
|
||||
|
||||
if (!tun_dst)
|
||||
if (!tun_dst) {
|
||||
reason = SKB_DROP_REASON_NOMEM;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
|
||||
|
||||
@ -1753,11 +1769,13 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
* is more robust and provides a little more security in
|
||||
* adding extensions to VXLAN.
|
||||
*/
|
||||
reason = SKB_DROP_REASON_VXLAN_INVALID_HDR;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (!raw_proto) {
|
||||
if (!vxlan_set_mac(vxlan, vs, skb, vni))
|
||||
reason = vxlan_set_mac(vxlan, vs, skb, vni);
|
||||
if (reason)
|
||||
goto drop;
|
||||
} else {
|
||||
skb_reset_mac_header(skb);
|
||||
@ -1773,7 +1791,8 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
if (!pskb_inet_may_pull(skb)) {
|
||||
reason = pskb_inet_may_pull_reason(skb);
|
||||
if (reason) {
|
||||
DEV_STATS_INC(vxlan->dev, rx_length_errors);
|
||||
DEV_STATS_INC(vxlan->dev, rx_errors);
|
||||
vxlan_vnifilter_count(vxlan, vni, vninode,
|
||||
@ -1785,6 +1804,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
oiph = skb->head + nh;
|
||||
|
||||
if (!vxlan_ecn_decapsulate(vs, oiph, skb)) {
|
||||
reason = SKB_DROP_REASON_IP_TUNNEL_ECN;
|
||||
DEV_STATS_INC(vxlan->dev, rx_frame_errors);
|
||||
DEV_STATS_INC(vxlan->dev, rx_errors);
|
||||
vxlan_vnifilter_count(vxlan, vni, vninode,
|
||||
@ -1799,6 +1819,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
dev_core_stats_rx_dropped_inc(vxlan->dev);
|
||||
vxlan_vnifilter_count(vxlan, vni, vninode,
|
||||
VXLAN_VNI_STATS_RX_DROPS, 0);
|
||||
reason = SKB_DROP_REASON_DEV_READY;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
@ -1811,8 +1832,9 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
return 0;
|
||||
|
||||
drop:
|
||||
reason = reason ?: SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
/* Consume bad packet */
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, reason);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2268,7 +2290,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
|
||||
rcu_read_lock();
|
||||
dev = skb->dev;
|
||||
if (unlikely(!(dev->flags & IFF_UP))) {
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_DEV_READY);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
@ -2319,7 +2341,7 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
|
||||
DEV_STATS_INC(dev, tx_errors);
|
||||
vxlan_vnifilter_count(vxlan, vni, NULL,
|
||||
VXLAN_VNI_STATS_TX_ERRORS, 0);
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_INVALID_HDR);
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
@ -2352,13 +2374,16 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||
bool use_cache;
|
||||
bool udp_sum = false;
|
||||
bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev));
|
||||
enum skb_drop_reason reason;
|
||||
bool no_eth_encap;
|
||||
__be32 vni = 0;
|
||||
|
||||
no_eth_encap = flags & VXLAN_F_GPE && skb->protocol != htons(ETH_P_TEB);
|
||||
if (!skb_vlan_inet_prepare(skb, no_eth_encap))
|
||||
reason = skb_vlan_inet_prepare(skb, no_eth_encap);
|
||||
if (reason)
|
||||
goto drop;
|
||||
|
||||
reason = SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
old_iph = ip_hdr(skb);
|
||||
|
||||
info = skb_tunnel_info(skb);
|
||||
@ -2462,6 +2487,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||
tos, use_cache ? dst_cache : NULL);
|
||||
if (IS_ERR(rt)) {
|
||||
err = PTR_ERR(rt);
|
||||
reason = SKB_DROP_REASON_IP_OUTNOROUTES;
|
||||
goto tx_error;
|
||||
}
|
||||
|
||||
@ -2513,8 +2539,10 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||
ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
|
||||
err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
|
||||
vni, md, flags, udp_sum);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
reason = SKB_DROP_REASON_NOMEM;
|
||||
goto tx_error;
|
||||
}
|
||||
|
||||
udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, saddr,
|
||||
pkey->u.ipv4.dst, tos, ttl, df,
|
||||
@ -2534,6 +2562,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||
if (IS_ERR(ndst)) {
|
||||
err = PTR_ERR(ndst);
|
||||
ndst = NULL;
|
||||
reason = SKB_DROP_REASON_IP_OUTNOROUTES;
|
||||
goto tx_error;
|
||||
}
|
||||
|
||||
@ -2574,8 +2603,10 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||
skb_scrub_packet(skb, xnet);
|
||||
err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
|
||||
vni, md, flags, udp_sum);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
reason = SKB_DROP_REASON_NOMEM;
|
||||
goto tx_error;
|
||||
}
|
||||
|
||||
udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev,
|
||||
&saddr, &pkey->u.ipv6.dst, tos, ttl,
|
||||
@ -2590,7 +2621,7 @@ out_unlock:
|
||||
drop:
|
||||
dev_core_stats_tx_dropped_inc(dev);
|
||||
vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);
|
||||
dev_kfree_skb(skb);
|
||||
kfree_skb_reason(skb, reason);
|
||||
return;
|
||||
|
||||
tx_error:
|
||||
@ -2602,7 +2633,7 @@ tx_error:
|
||||
dst_release(ndst);
|
||||
DEV_STATS_INC(dev, tx_errors);
|
||||
vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0);
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, reason);
|
||||
}
|
||||
|
||||
static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,
|
||||
@ -2708,7 +2739,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (info && info->mode & IP_TUNNEL_INFO_TX)
|
||||
vxlan_xmit_one(skb, dev, vni, NULL, false);
|
||||
else
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_TUNNEL_TXINFO);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
}
|
||||
@ -2771,7 +2802,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
dev_core_stats_tx_dropped_inc(dev);
|
||||
vxlan_vnifilter_count(vxlan, vni, NULL,
|
||||
VXLAN_VNI_STATS_TX_DROPS, 0);
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
}
|
||||
@ -2794,7 +2825,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (fdst)
|
||||
vxlan_xmit_one(skb, dev, vni, fdst, did_rsc);
|
||||
else
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
|
||||
}
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
|
@ -1712,7 +1712,7 @@ netdev_tx_t vxlan_mdb_xmit(struct vxlan_dev *vxlan,
|
||||
vxlan_xmit_one(skb, vxlan->dev, src_vni,
|
||||
rcu_dereference(fremote->rd), false);
|
||||
else
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
@ -3130,9 +3130,15 @@ static inline int skb_inner_network_offset(const struct sk_buff *skb)
|
||||
return skb_inner_network_header(skb) - skb->data;
|
||||
}
|
||||
|
||||
static inline enum skb_drop_reason
|
||||
pskb_network_may_pull_reason(struct sk_buff *skb, unsigned int len)
|
||||
{
|
||||
return pskb_may_pull_reason(skb, skb_network_offset(skb) + len);
|
||||
}
|
||||
|
||||
static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len)
|
||||
{
|
||||
return pskb_may_pull(skb, skb_network_offset(skb) + len);
|
||||
return pskb_network_may_pull_reason(skb, len) == SKB_NOT_DROPPED_YET;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -92,6 +92,14 @@
|
||||
FN(PACKET_SOCK_ERROR) \
|
||||
FN(TC_CHAIN_NOTFOUND) \
|
||||
FN(TC_RECLASSIFY_LOOP) \
|
||||
FN(VXLAN_INVALID_HDR) \
|
||||
FN(VXLAN_VNI_NOT_FOUND) \
|
||||
FN(MAC_INVALID_SOURCE) \
|
||||
FN(VXLAN_ENTRY_EXISTS) \
|
||||
FN(VXLAN_NO_REMOTE) \
|
||||
FN(IP_TUNNEL_ECN) \
|
||||
FN(TUNNEL_TXINFO) \
|
||||
FN(LOCAL_MAC) \
|
||||
FNe(MAX)
|
||||
|
||||
/**
|
||||
@ -418,6 +426,38 @@ enum skb_drop_reason {
|
||||
* iterations.
|
||||
*/
|
||||
SKB_DROP_REASON_TC_RECLASSIFY_LOOP,
|
||||
/**
|
||||
* @SKB_DROP_REASON_VXLAN_INVALID_HDR: VXLAN header is invalid. E.g.:
|
||||
* 1) reserved fields are not zero
|
||||
* 2) "I" flag is not set
|
||||
*/
|
||||
SKB_DROP_REASON_VXLAN_INVALID_HDR,
|
||||
/** @SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND: no VXLAN device found for VNI */
|
||||
SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND,
|
||||
/** @SKB_DROP_REASON_MAC_INVALID_SOURCE: source mac is invalid */
|
||||
SKB_DROP_REASON_MAC_INVALID_SOURCE,
|
||||
/**
|
||||
* @SKB_DROP_REASON_VXLAN_ENTRY_EXISTS: trying to migrate a static
|
||||
* entry or an entry pointing to a nexthop.
|
||||
*/
|
||||
SKB_DROP_REASON_VXLAN_ENTRY_EXISTS,
|
||||
/** @SKB_DROP_REASON_VXLAN_NO_REMOTE: no remote found for xmit */
|
||||
SKB_DROP_REASON_VXLAN_NO_REMOTE,
|
||||
/**
|
||||
* @SKB_DROP_REASON_IP_TUNNEL_ECN: skb is dropped according to
|
||||
* RFC 6040 4.2, see __INET_ECN_decapsulate() for detail.
|
||||
*/
|
||||
SKB_DROP_REASON_IP_TUNNEL_ECN,
|
||||
/**
|
||||
* @SKB_DROP_REASON_TUNNEL_TXINFO: packet without necessary metadata
|
||||
* reached a device which is in "external" mode.
|
||||
*/
|
||||
SKB_DROP_REASON_TUNNEL_TXINFO,
|
||||
/**
|
||||
* @SKB_DROP_REASON_LOCAL_MAC: the source MAC address is equal to
|
||||
* the MAC address of the local netdev.
|
||||
*/
|
||||
SKB_DROP_REASON_LOCAL_MAC,
|
||||
/**
|
||||
* @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which
|
||||
* shouldn't be used as a real 'reason' - only for tracing code gen
|
||||
|
@ -439,7 +439,8 @@ int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *op,
|
||||
int ip_tunnel_encap_setup(struct ip_tunnel *t,
|
||||
struct ip_tunnel_encap *ipencap);
|
||||
|
||||
static inline bool pskb_inet_may_pull(struct sk_buff *skb)
|
||||
static inline enum skb_drop_reason
|
||||
pskb_inet_may_pull_reason(struct sk_buff *skb)
|
||||
{
|
||||
int nhlen;
|
||||
|
||||
@ -456,16 +457,22 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb)
|
||||
nhlen = 0;
|
||||
}
|
||||
|
||||
return pskb_network_may_pull(skb, nhlen);
|
||||
return pskb_network_may_pull_reason(skb, nhlen);
|
||||
}
|
||||
|
||||
static inline bool pskb_inet_may_pull(struct sk_buff *skb)
|
||||
{
|
||||
return pskb_inet_may_pull_reason(skb) == SKB_NOT_DROPPED_YET;
|
||||
}
|
||||
|
||||
/* Variant of pskb_inet_may_pull().
|
||||
*/
|
||||
static inline bool skb_vlan_inet_prepare(struct sk_buff *skb,
|
||||
bool inner_proto_inherit)
|
||||
static inline enum skb_drop_reason
|
||||
skb_vlan_inet_prepare(struct sk_buff *skb, bool inner_proto_inherit)
|
||||
{
|
||||
int nhlen = 0, maclen = inner_proto_inherit ? 0 : ETH_HLEN;
|
||||
__be16 type = skb->protocol;
|
||||
enum skb_drop_reason reason;
|
||||
|
||||
/* Essentially this is skb_protocol(skb, true)
|
||||
* And we get MAC len.
|
||||
@ -486,11 +493,13 @@ static inline bool skb_vlan_inet_prepare(struct sk_buff *skb,
|
||||
/* For ETH_P_IPV6/ETH_P_IP we make sure to pull
|
||||
* a base network header in skb->head.
|
||||
*/
|
||||
if (!pskb_may_pull(skb, maclen + nhlen))
|
||||
return false;
|
||||
reason = pskb_may_pull_reason(skb, maclen + nhlen);
|
||||
if (reason)
|
||||
return reason;
|
||||
|
||||
skb_set_network_header(skb, maclen);
|
||||
return true;
|
||||
|
||||
return SKB_NOT_DROPPED_YET;
|
||||
}
|
||||
|
||||
static inline int ip_encap_hlen(struct ip_tunnel_encap *e)
|
||||
|
Loading…
x
Reference in New Issue
Block a user