mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	nsh: add GSO support
Add a new nsh/ directory. It currently holds only GSO functions but more will come: in particular, code shared by openvswitch and tc to manipulate NSH headers. For now, assume there's no hardware support for NSH segmentation. We can always introduce netdev->nsh_features later. Signed-off-by: Jiri Benc <jbenc@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									1f0b7744c5
								
							
						
					
					
						commit
						c411ed8545
					
				
					 5 changed files with 103 additions and 0 deletions
				
			
		|  | @ -235,6 +235,7 @@ source "net/openvswitch/Kconfig" | |||
| source "net/vmw_vsock/Kconfig" | ||||
| source "net/netlink/Kconfig" | ||||
| source "net/mpls/Kconfig" | ||||
| source "net/nsh/Kconfig" | ||||
| source "net/hsr/Kconfig" | ||||
| source "net/switchdev/Kconfig" | ||||
| source "net/l3mdev/Kconfig" | ||||
|  |  | |||
|  | @ -75,6 +75,7 @@ obj-$(CONFIG_NET_IFE)		+= ife/ | |||
| obj-$(CONFIG_OPENVSWITCH)	+= openvswitch/ | ||||
| obj-$(CONFIG_VSOCKETS)	+= vmw_vsock/ | ||||
| obj-$(CONFIG_MPLS)		+= mpls/ | ||||
| obj-$(CONFIG_NET_NSH)		+= nsh/ | ||||
| obj-$(CONFIG_HSR)		+= hsr/ | ||||
| ifneq ($(CONFIG_NET_SWITCHDEV),) | ||||
| obj-y				+= switchdev/ | ||||
|  |  | |||
							
								
								
									
										9
									
								
								net/nsh/Kconfig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								net/nsh/Kconfig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| menuconfig NET_NSH | ||||
| 	tristate "Network Service Header (NSH) protocol" | ||||
| 	default n | ||||
| 	---help--- | ||||
| 	  Network Service Header is an implementation of Service Function | ||||
| 	  Chaining (RFC 7665). The current implementation in Linux supports | ||||
| 	  only MD type 1 and only with the openvswitch module. | ||||
| 
 | ||||
| 	  If unsure, say N. | ||||
							
								
								
									
										1
									
								
								net/nsh/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								net/nsh/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| obj-$(CONFIG_NET_NSH) += nsh.o | ||||
							
								
								
									
										91
									
								
								net/nsh/nsh.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								net/nsh/nsh.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | |||
| /*
 | ||||
|  * Network Service Header | ||||
|  * | ||||
|  * Copyright (c) 2017 Red Hat, Inc. -- Jiri Benc <jbenc@redhat.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/module.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/skbuff.h> | ||||
| #include <net/nsh.h> | ||||
| #include <net/tun_proto.h> | ||||
| 
 | ||||
| static struct sk_buff *nsh_gso_segment(struct sk_buff *skb, | ||||
| 				       netdev_features_t features) | ||||
| { | ||||
| 	struct sk_buff *segs = ERR_PTR(-EINVAL); | ||||
| 	unsigned int nsh_len, mac_len; | ||||
| 	__be16 proto; | ||||
| 	int nhoff; | ||||
| 
 | ||||
| 	skb_reset_network_header(skb); | ||||
| 
 | ||||
| 	nhoff = skb->network_header - skb->mac_header; | ||||
| 	mac_len = skb->mac_len; | ||||
| 
 | ||||
| 	if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN))) | ||||
| 		goto out; | ||||
| 	nsh_len = nsh_hdr_len(nsh_hdr(skb)); | ||||
| 	if (unlikely(!pskb_may_pull(skb, nsh_len))) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	proto = tun_p_to_eth_p(nsh_hdr(skb)->np); | ||||
| 	if (!proto) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	__skb_pull(skb, nsh_len); | ||||
| 
 | ||||
| 	skb_reset_mac_header(skb); | ||||
| 	skb_reset_mac_len(skb); | ||||
| 	skb->protocol = proto; | ||||
| 
 | ||||
| 	features &= NETIF_F_SG; | ||||
| 	segs = skb_mac_gso_segment(skb, features); | ||||
| 	if (IS_ERR_OR_NULL(segs)) { | ||||
| 		skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len, | ||||
| 				     skb->network_header - nhoff, | ||||
| 				     mac_len); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	for (skb = segs; skb; skb = skb->next) { | ||||
| 		skb->protocol = htons(ETH_P_NSH); | ||||
| 		__skb_push(skb, nsh_len); | ||||
| 		skb_set_mac_header(skb, -nhoff); | ||||
| 		skb->network_header = skb->mac_header + mac_len; | ||||
| 		skb->mac_len = mac_len; | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	return segs; | ||||
| } | ||||
| 
 | ||||
| static struct packet_offload nsh_packet_offload __read_mostly = { | ||||
| 	.type = htons(ETH_P_NSH), | ||||
| 	.priority = 15, | ||||
| 	.callbacks = { | ||||
| 		.gso_segment = nsh_gso_segment, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static int __init nsh_init_module(void) | ||||
| { | ||||
| 	dev_add_offload(&nsh_packet_offload); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void __exit nsh_cleanup_module(void) | ||||
| { | ||||
| 	dev_remove_offload(&nsh_packet_offload); | ||||
| } | ||||
| 
 | ||||
| module_init(nsh_init_module); | ||||
| module_exit(nsh_cleanup_module); | ||||
| 
 | ||||
| MODULE_AUTHOR("Jiri Benc <jbenc@redhat.com>"); | ||||
| MODULE_DESCRIPTION("NSH protocol"); | ||||
| MODULE_LICENSE("GPL v2"); | ||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Jiri Benc
						Jiri Benc