-
Notifications
You must be signed in to change notification settings - Fork 562
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
- Loading branch information
Showing
5 changed files
with
103 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
obj-$(CONFIG_NET_NSH) += nsh.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* Network Service Header | ||
* | ||
* Copyright (c) 2017 Red Hat, Inc. -- Jiri Benc <[email protected]> | ||
* | ||
* 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 <[email protected]>"); | ||
MODULE_DESCRIPTION("NSH protocol"); | ||
MODULE_LICENSE("GPL v2"); |