diff mbox series

[v2,net-next] macvlan: Add nodst option to macvlan type source

Message ID 2afc4d46-aa9b-a7db-d872-d02163b1f29c@jbeekman.nl (mailing list archive)
State Accepted
Commit 427f0c8c194b22edcafef1b0a42995ddc5c2227d
Delegated to: Netdev Maintainers
Headers show
Series [v2,net-next] macvlan: Add nodst option to macvlan type source | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Clearly marked for net-next
netdev/subject_prefix success Link
netdev/cc_maintainers success CCed 3 of 3 maintainers
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 6718 this patch: 6718
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 60 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 6931 this patch: 6931
netdev/header_inline success Link

Commit Message

Jethro Beekman April 25, 2021, 9:22 a.m. UTC
The default behavior for source MACVLAN is to duplicate packets to
appropriate type source devices, and then do the normal destination MACVLAN
flow. This patch adds an option to skip destination MACVLAN processing if
any matching source MACVLAN device has the option set.

This allows setting up a "catch all" device for source MACVLAN: create one
or more devices with type source nodst, and one device with e.g. type vepa,
and incoming traffic will be received on exactly one device.

v2: netdev wants non-standard line length

Signed-off-by: Jethro Beekman <kernel@jbeekman.nl>
---
 drivers/net/macvlan.c        | 19 ++++++++++++++-----
 include/uapi/linux/if_link.h |  1 +
 2 files changed, 15 insertions(+), 5 deletions(-)

Comments

Leon Romanovsky April 25, 2021, 11:12 a.m. UTC | #1
On Sun, Apr 25, 2021 at 11:22:03AM +0200, Jethro Beekman wrote:
> The default behavior for source MACVLAN is to duplicate packets to
> appropriate type source devices, and then do the normal destination MACVLAN
> flow. This patch adds an option to skip destination MACVLAN processing if
> any matching source MACVLAN device has the option set.
> 
> This allows setting up a "catch all" device for source MACVLAN: create one
> or more devices with type source nodst, and one device with e.g. type vepa,
> and incoming traffic will be received on exactly one device.
> 
> v2: netdev wants non-standard line length

Can you please put the changelog after "---"? So it won't be part of
commit message in the git log.

Thanks

> 
> Signed-off-by: Jethro Beekman <kernel@jbeekman.nl>
> ---
>  drivers/net/macvlan.c        | 19 ++++++++++++++-----
>  include/uapi/linux/if_link.h |  1 +
>  2 files changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
> index 9a9a5cf36a4b..7427b989607e 100644
> --- a/drivers/net/macvlan.c
> +++ b/drivers/net/macvlan.c
> @@ -423,18 +423,24 @@ static void macvlan_forward_source_one(struct sk_buff *skb,
>  	macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, false);
>  }
>  
> -static void macvlan_forward_source(struct sk_buff *skb,
> +static bool macvlan_forward_source(struct sk_buff *skb,
>  				   struct macvlan_port *port,
>  				   const unsigned char *addr)
>  {
>  	struct macvlan_source_entry *entry;
>  	u32 idx = macvlan_eth_hash(addr);
>  	struct hlist_head *h = &port->vlan_source_hash[idx];
> +	bool consume = false;
>  
>  	hlist_for_each_entry_rcu(entry, h, hlist) {
> -		if (ether_addr_equal_64bits(entry->addr, addr))
> +		if (ether_addr_equal_64bits(entry->addr, addr)) {
> +			if (entry->vlan->flags & MACVLAN_FLAG_NODST)
> +				consume = true;
>  			macvlan_forward_source_one(skb, entry->vlan);
> +		}
>  	}
> +
> +	return consume;
>  }
>  
>  /* called under rcu_read_lock() from netif_receive_skb */
> @@ -463,7 +469,8 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
>  			return RX_HANDLER_CONSUMED;
>  		*pskb = skb;
>  		eth = eth_hdr(skb);
> -		macvlan_forward_source(skb, port, eth->h_source);
> +		if (macvlan_forward_source(skb, port, eth->h_source))
> +			return RX_HANDLER_CONSUMED;
>  		src = macvlan_hash_lookup(port, eth->h_source);
>  		if (src && src->mode != MACVLAN_MODE_VEPA &&
>  		    src->mode != MACVLAN_MODE_BRIDGE) {
> @@ -482,7 +489,8 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
>  		return RX_HANDLER_PASS;
>  	}
>  
> -	macvlan_forward_source(skb, port, eth->h_source);
> +	if (macvlan_forward_source(skb, port, eth->h_source))
> +		return RX_HANDLER_CONSUMED;
>  	if (macvlan_passthru(port))
>  		vlan = list_first_or_null_rcu(&port->vlans,
>  					      struct macvlan_dev, list);
> @@ -1286,7 +1294,8 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[],
>  		return 0;
>  
>  	if (data[IFLA_MACVLAN_FLAGS] &&
> -	    nla_get_u16(data[IFLA_MACVLAN_FLAGS]) & ~MACVLAN_FLAG_NOPROMISC)
> +	    nla_get_u16(data[IFLA_MACVLAN_FLAGS]) & ~(MACVLAN_FLAG_NOPROMISC |
> +						      MACVLAN_FLAG_NODST))
>  		return -EINVAL;
>  
>  	if (data[IFLA_MACVLAN_MODE]) {
> diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> index 91c8dda6d95d..cd5b382a4138 100644
> --- a/include/uapi/linux/if_link.h
> +++ b/include/uapi/linux/if_link.h
> @@ -614,6 +614,7 @@ enum macvlan_macaddr_mode {
>  };
>  
>  #define MACVLAN_FLAG_NOPROMISC	1
> +#define MACVLAN_FLAG_NODST	2 /* skip dst macvlan if matching src macvlan */
>  
>  /* VRF section */
>  enum {
> -- 
> 2.31.1
>
patchwork-bot+netdevbpf@kernel.org April 26, 2021, 1:40 a.m. UTC | #2
Hello:

This patch was applied to netdev/net-next.git (refs/heads/master):

On Sun, 25 Apr 2021 11:22:03 +0200 you wrote:
> The default behavior for source MACVLAN is to duplicate packets to
> appropriate type source devices, and then do the normal destination MACVLAN
> flow. This patch adds an option to skip destination MACVLAN processing if
> any matching source MACVLAN device has the option set.
> 
> This allows setting up a "catch all" device for source MACVLAN: create one
> or more devices with type source nodst, and one device with e.g. type vepa,
> and incoming traffic will be received on exactly one device.
> 
> [...]

Here is the summary with links:
  - [v2,net-next] macvlan: Add nodst option to macvlan type source
    https://git.kernel.org/netdev/net-next/c/427f0c8c194b

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
diff mbox series

Patch

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 9a9a5cf36a4b..7427b989607e 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -423,18 +423,24 @@  static void macvlan_forward_source_one(struct sk_buff *skb,
 	macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, false);
 }
 
-static void macvlan_forward_source(struct sk_buff *skb,
+static bool macvlan_forward_source(struct sk_buff *skb,
 				   struct macvlan_port *port,
 				   const unsigned char *addr)
 {
 	struct macvlan_source_entry *entry;
 	u32 idx = macvlan_eth_hash(addr);
 	struct hlist_head *h = &port->vlan_source_hash[idx];
+	bool consume = false;
 
 	hlist_for_each_entry_rcu(entry, h, hlist) {
-		if (ether_addr_equal_64bits(entry->addr, addr))
+		if (ether_addr_equal_64bits(entry->addr, addr)) {
+			if (entry->vlan->flags & MACVLAN_FLAG_NODST)
+				consume = true;
 			macvlan_forward_source_one(skb, entry->vlan);
+		}
 	}
+
+	return consume;
 }
 
 /* called under rcu_read_lock() from netif_receive_skb */
@@ -463,7 +469,8 @@  static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
 			return RX_HANDLER_CONSUMED;
 		*pskb = skb;
 		eth = eth_hdr(skb);
-		macvlan_forward_source(skb, port, eth->h_source);
+		if (macvlan_forward_source(skb, port, eth->h_source))
+			return RX_HANDLER_CONSUMED;
 		src = macvlan_hash_lookup(port, eth->h_source);
 		if (src && src->mode != MACVLAN_MODE_VEPA &&
 		    src->mode != MACVLAN_MODE_BRIDGE) {
@@ -482,7 +489,8 @@  static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
 		return RX_HANDLER_PASS;
 	}
 
-	macvlan_forward_source(skb, port, eth->h_source);
+	if (macvlan_forward_source(skb, port, eth->h_source))
+		return RX_HANDLER_CONSUMED;
 	if (macvlan_passthru(port))
 		vlan = list_first_or_null_rcu(&port->vlans,
 					      struct macvlan_dev, list);
@@ -1286,7 +1294,8 @@  static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[],
 		return 0;
 
 	if (data[IFLA_MACVLAN_FLAGS] &&
-	    nla_get_u16(data[IFLA_MACVLAN_FLAGS]) & ~MACVLAN_FLAG_NOPROMISC)
+	    nla_get_u16(data[IFLA_MACVLAN_FLAGS]) & ~(MACVLAN_FLAG_NOPROMISC |
+						      MACVLAN_FLAG_NODST))
 		return -EINVAL;
 
 	if (data[IFLA_MACVLAN_MODE]) {
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 91c8dda6d95d..cd5b382a4138 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -614,6 +614,7 @@  enum macvlan_macaddr_mode {
 };
 
 #define MACVLAN_FLAG_NOPROMISC	1
+#define MACVLAN_FLAG_NODST	2 /* skip dst macvlan if matching src macvlan */
 
 /* VRF section */
 enum {