Commit 12f077a7 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'net-ip-add-drop-reasons-to-input-route'

Menglong Dong says:

====================
net: ip: add drop reasons to input route

In this series, we mainly add some skb drop reasons to the input path of
ip routing, and we make the following functions return drop reasons:

  fib_validate_source()
  ip_route_input_mc()
  ip_mc_validate_source()
  ip_route_input_slow()
  ip_route_input_rcu()
  ip_route_input_noref()
  ip_route_input()
  ip_mkroute_input()
  __mkroute_input()
  ip_route_use_hint()

And following new skb drop reasons are added:

  SKB_DROP_REASON_IP_LOCAL_SOURCE
  SKB_DROP_REASON_IP_INVALID_SOURCE
  SKB_DROP_REASON_IP_LOCALNET
  SKB_DROP_REASON_IP_INVALID_DEST

Changes since v4:
- in the 6th patch: remove the unneeded "else" in ip_expire()
- in the 8th patch: delete the unneeded comment in __mkroute_input()
- in the 9th patch: replace "return 0" with "return SKB_NOT_DROPPED_YET"
  in ip_route_use_hint()

Changes since v3:
- don't refactor fib_validate_source/__fib_validate_source, and introduce
  a wrapper for fib_validate_source() instead in the 1st patch.
- some small adjustment in the 4-7 patches

Changes since v2:
- refactor fib_validate_source and __fib_validate_source to make
  fib_validate_source return drop reasons
- add the 9th and 10th patches to make this series cover the input route
  code path

Changes since v1:
- make ip_route_input_noref/ip_route_input_rcu/ip_route_input_slow return
  drop reasons, instead of passing a local variable to their function
  arguments.
====================

Link: https://patch.msgid.link/20241107125601.1076814-1-dongml2@chinatelecom.cn


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 544070db 479aed04
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -76,6 +76,10 @@
	FN(INVALID_PROTO)		\
	FN(IP_INADDRERRORS)		\
	FN(IP_INNOROUTES)		\
	FN(IP_LOCAL_SOURCE)		\
	FN(IP_INVALID_SOURCE)		\
	FN(IP_LOCALNET)			\
	FN(IP_INVALID_DEST)		\
	FN(PKT_TOO_BIG)			\
	FN(DUP_FRAG)			\
	FN(FRAG_REASM_TIMEOUT)		\
@@ -100,6 +104,7 @@
	FN(IP_TUNNEL_ECN)		\
	FN(TUNNEL_TXINFO)		\
	FN(LOCAL_MAC)			\
	FN(ARP_PVLAN_DISABLE)		\
	FNe(MAX)

/**
@@ -373,6 +378,21 @@ enum skb_drop_reason {
	 * IPSTATS_MIB_INADDRERRORS
	 */
	SKB_DROP_REASON_IP_INNOROUTES,
	/** @SKB_DROP_REASON_IP_LOCAL_SOURCE: the source ip is local */
	SKB_DROP_REASON_IP_LOCAL_SOURCE,
	/**
	 * @SKB_DROP_REASON_IP_INVALID_SOURCE: the source ip is invalid:
	 * 1) source ip is multicast or limited broadcast
	 * 2) source ip is zero and not IGMP
	 */
	SKB_DROP_REASON_IP_INVALID_SOURCE,
	/** @SKB_DROP_REASON_IP_LOCALNET: source or dest ip is local net */
	SKB_DROP_REASON_IP_LOCALNET,
	/**
	 * @SKB_DROP_REASON_IP_INVALID_DEST: the dest ip is invalid:
	 * 1) dest ip is 0
	 */
	SKB_DROP_REASON_IP_INVALID_DEST,
	/**
	 * @SKB_DROP_REASON_PKT_TOO_BIG: packet size is too big (maybe exceed the
	 * MTU)
@@ -458,6 +478,12 @@ enum skb_drop_reason {
	 * the MAC address of the local netdev.
	 */
	SKB_DROP_REASON_LOCAL_MAC,
	/**
	 * @SKB_DROP_REASON_ARP_PVLAN_DISABLE: packet which is not IP is
	 * forwarded to the in_dev, and the proxy_arp_pvlan is not
	 * enabled.
	 */
	SKB_DROP_REASON_ARP_PVLAN_DISABLE,
	/**
	 * @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which
	 * shouldn't be used as a real 'reason' - only for tracing code gen
+12 −0
Original line number Diff line number Diff line
@@ -452,6 +452,18 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
			dscp_t dscp, int oif, struct net_device *dev,
			struct in_device *idev, u32 *itag);

static inline enum skb_drop_reason
fib_validate_source_reason(struct sk_buff *skb, __be32 src, __be32 dst,
			   dscp_t dscp, int oif, struct net_device *dev,
			   struct in_device *idev, u32 *itag)
{
	int err = fib_validate_source(skb, src, dst, dscp, oif, dev, idev,
				      itag);
	if (err < 0)
		return -err;
	return SKB_NOT_DROPPED_YET;
}

#ifdef CONFIG_IP_ROUTE_CLASSID
static inline int fib_num_tclassid_users(struct net *net)
{
+19 −15
Original line number Diff line number Diff line
@@ -199,30 +199,34 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4
	return ip_route_output_key(net, fl4);
}

int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
enum skb_drop_reason
ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
		      dscp_t dscp, struct net_device *dev,
		      struct in_device *in_dev, u32 *itag);
int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
enum skb_drop_reason
ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
		     dscp_t dscp, struct net_device *dev);
int ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
enum skb_drop_reason
ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
		  dscp_t dscp, struct net_device *dev,
		  const struct sk_buff *hint);

static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
				 dscp_t dscp, struct net_device *devin)
static inline enum skb_drop_reason
ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, dscp_t dscp,
	       struct net_device *devin)
{
	int err;
	enum skb_drop_reason reason;

	rcu_read_lock();
	err = ip_route_input_noref(skb, dst, src, dscp, devin);
	if (!err) {
	reason = ip_route_input_noref(skb, dst, src, dscp, devin);
	if (!reason) {
		skb_dst_force(skb);
		if (!skb_dst(skb))
			err = -EINVAL;
			reason = SKB_DROP_REASON_NOT_SPECIFIED;
	}
	rcu_read_unlock();

	return err;
	return reason;
}

void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, int oif,
+6 −5
Original line number Diff line number Diff line
@@ -373,8 +373,8 @@ static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_
	struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
	struct net_device *dev = skb->dev, *br_indev;
	const struct iphdr *iph = ip_hdr(skb);
	enum skb_drop_reason reason;
	struct rtable *rt;
	int err;

	br_indev = nf_bridge_get_physindev(skb, net);
	if (!br_indev) {
@@ -390,9 +390,9 @@ static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_
	}
	nf_bridge->in_prerouting = 0;
	if (br_nf_ipv4_daddr_was_changed(skb, nf_bridge)) {
		err = ip_route_input(skb, iph->daddr, iph->saddr,
		reason = ip_route_input(skb, iph->daddr, iph->saddr,
					ip4h_dscp(iph), dev);
		if (err) {
		if (reason) {
			struct in_device *in_dev = __in_dev_get_rcu(dev);

			/* If err equals -EHOSTUNREACH the error is due to a
@@ -402,7 +402,8 @@ static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_
			 * martian destinations: loopback destinations and destination
			 * 0.0.0.0. In both cases the packet will be dropped because the
			 * destination is the loopback device and not the bridge. */
			if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev))
			if (reason != SKB_DROP_REASON_IP_INADDRERRORS || !in_dev ||
			    IN_DEV_FORWARD(in_dev))
				goto free_skb;

			rt = ip_route_output(net, iph->daddr, 0,
+4 −2
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,

static int bpf_lwt_input_reroute(struct sk_buff *skb)
{
	enum skb_drop_reason reason;
	int err = -EINVAL;

	if (skb->protocol == htons(ETH_P_IP)) {
@@ -96,8 +97,9 @@ static int bpf_lwt_input_reroute(struct sk_buff *skb)

		dev_hold(dev);
		skb_dst_drop(skb);
		err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
		reason = ip_route_input_noref(skb, iph->daddr, iph->saddr,
					      ip4h_dscp(iph), dev);
		err = reason ? -EINVAL : 0;
		dev_put(dev);
	} else if (skb->protocol == htons(ETH_P_IPV6)) {
		skb_dst_drop(skb);
Loading