From: William Tu <u9012063@gmail.com>
To: netdev@vger.kernel.org
Cc: pshelar@ovn.org
Subject: [PATCHv6 net-next 1/3] net: erspan: use bitfield instead of mask and offset
Date: Thu, 25 Jan 2018 13:20:09 -0800 [thread overview]
Message-ID: <1516915211-5869-2-git-send-email-u9012063@gmail.com> (raw)
In-Reply-To: <1516915211-5869-1-git-send-email-u9012063@gmail.com>
Originally the erspan fields are defined as a group into a __be16 field,
and use mask and offset to access each field. This is more costly due to
calling ntohs/htons. The patch changes it to use bitfields.
Signed-off-by: William Tu <u9012063@gmail.com>
---
include/net/erspan.h | 127 ++++++++++++++++++++++++++++++++++++++-------------
net/ipv4/ip_gre.c | 38 ++++++---------
net/ipv6/ip6_gre.c | 36 ++++++---------
3 files changed, 121 insertions(+), 80 deletions(-)
diff --git a/include/net/erspan.h b/include/net/erspan.h
index 712ea1b1f4db..6d30fe898286 100644
--- a/include/net/erspan.h
+++ b/include/net/erspan.h
@@ -65,16 +65,30 @@
#define GRA_MASK 0x0006
#define O_MASK 0x0001
+#define HWID_OFFSET 4
+#define DIR_OFFSET 3
+
/* ERSPAN version 2 metadata header */
struct erspan_md2 {
__be32 timestamp;
__be16 sgt; /* security group tag */
- __be16 flags;
-#define P_OFFSET 15
-#define FT_OFFSET 10
-#define HWID_OFFSET 4
-#define DIR_OFFSET 3
-#define GRA_OFFSET 1
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 hwid_upper:2,
+ ft:5,
+ p:1;
+ __u8 o:1,
+ gra:2,
+ dir:1,
+ hwid:4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u8 p:1,
+ ft:5,
+ hwid_upper:2;
+ __u8 hwid:4,
+ dir:1,
+ gra:2,
+ o:1;
+#endif
};
enum erspan_encap_type {
@@ -95,15 +109,62 @@ struct erspan_metadata {
};
struct erspan_base_hdr {
- __be16 ver_vlan;
-#define VER_OFFSET 12
- __be16 session_id;
-#define COS_OFFSET 13
-#define EN_OFFSET 11
-#define BSO_OFFSET EN_OFFSET
-#define T_OFFSET 10
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 vlan_upper:4,
+ ver:4;
+ __u8 vlan:8;
+ __u8 session_id_upper:2,
+ t:1,
+ en:2,
+ cos:3;
+ __u8 session_id:8;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u8 ver: 4,
+ vlan_upper:4;
+ __u8 vlan:8;
+ __u8 cos:3,
+ en:2,
+ t:1,
+ session_id_upper:2;
+ __u8 session_id:8;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
};
+static inline void set_session_id(struct erspan_base_hdr *ershdr, u16 id)
+{
+ ershdr->session_id = id & 0xff;
+ ershdr->session_id_upper = (id >> 8) & 0x3;
+}
+
+static inline u16 get_session_id(const struct erspan_base_hdr *ershdr)
+{
+ return (ershdr->session_id_upper << 8) + ershdr->session_id;
+}
+
+static inline void set_vlan(struct erspan_base_hdr *ershdr, u16 vlan)
+{
+ ershdr->vlan = vlan & 0xff;
+ ershdr->vlan_upper = (vlan >> 8) & 0xf;
+}
+
+static inline u16 get_vlan(const struct erspan_base_hdr *ershdr)
+{
+ return (ershdr->vlan_upper << 8) + ershdr->vlan;
+}
+
+static inline void set_hwid(struct erspan_md2 *md2, u8 hwid)
+{
+ md2->hwid = hwid & 0xf;
+ md2->hwid_upper = (hwid >> 4) & 0x3;
+}
+
+static inline u8 get_hwid(const struct erspan_md2 *md2)
+{
+ return (md2->hwid_upper << 4) + md2->hwid;
+}
+
static inline int erspan_hdr_len(int version)
{
return sizeof(struct erspan_base_hdr) +
@@ -120,7 +181,7 @@ static inline u8 tos_to_cos(u8 tos)
}
static inline void erspan_build_header(struct sk_buff *skb,
- __be32 id, u32 index,
+ u32 id, u32 index,
bool truncate, bool is_ipv4)
{
struct ethhdr *eth = (struct ethhdr *)skb->data;
@@ -154,12 +215,12 @@ static inline void erspan_build_header(struct sk_buff *skb,
memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V1_MDSIZE);
/* Build base header */
- ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
- (ERSPAN_VERSION << VER_OFFSET));
- ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) |
- ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) |
- (enc_type << EN_OFFSET & EN_MASK) |
- ((truncate << T_OFFSET) & T_MASK));
+ ershdr->ver = ERSPAN_VERSION;
+ ershdr->cos = tos_to_cos(tos);
+ ershdr->en = enc_type;
+ ershdr->t = truncate;
+ set_vlan(ershdr, vlan_tci);
+ set_session_id(ershdr, id);
/* Build metadata */
ersmd = (struct erspan_metadata *)(ershdr + 1);
@@ -187,7 +248,7 @@ static inline __be32 erspan_get_timestamp(void)
}
static inline void erspan_build_header_v2(struct sk_buff *skb,
- __be32 id, u8 direction, u16 hwid,
+ u32 id, u8 direction, u16 hwid,
bool truncate, bool is_ipv4)
{
struct ethhdr *eth = (struct ethhdr *)skb->data;
@@ -198,7 +259,6 @@ static inline void erspan_build_header_v2(struct sk_buff *skb,
__be16 tci;
} *qp;
u16 vlan_tci = 0;
- u16 session_id;
u8 gra = 0; /* 100 usec */
u8 bso = 0; /* Bad/Short/Oversized */
u8 sgt = 0;
@@ -221,22 +281,23 @@ static inline void erspan_build_header_v2(struct sk_buff *skb,
memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V2_MDSIZE);
/* Build base header */
- ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
- (ERSPAN_VERSION2 << VER_OFFSET));
- session_id = (u16)(ntohl(id) & ID_MASK) |
- ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) |
- (bso << BSO_OFFSET & BSO_MASK) |
- ((truncate << T_OFFSET) & T_MASK);
- ershdr->session_id = htons(session_id);
+ ershdr->ver = ERSPAN_VERSION2;
+ ershdr->cos = tos_to_cos(tos);
+ ershdr->en = bso;
+ ershdr->t = truncate;
+ set_vlan(ershdr, vlan_tci);
+ set_session_id(ershdr, id);
/* Build metadata */
md = (struct erspan_metadata *)(ershdr + 1);
md->u.md2.timestamp = erspan_get_timestamp();
md->u.md2.sgt = htons(sgt);
- md->u.md2.flags = htons(((1 << P_OFFSET) & P_MASK) |
- ((hwid << HWID_OFFSET) & HWID_MASK) |
- ((direction << DIR_OFFSET) & DIR_MASK) |
- ((gra << GRA_OFFSET) & GRA_MASK));
+ md->u.md2.p = 1;
+ md->u.md2.ft = 0;
+ md->u.md2.dir = direction;
+ md->u.md2.gra = gra;
+ md->u.md2.o = 0;
+ set_hwid(&md->u.md2, hwid);
}
#endif
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index b61f2285816d..6ec670fbbbdd 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -114,7 +114,7 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
static struct rtnl_link_ops ipgre_link_ops __read_mostly;
static int ipgre_tunnel_init(struct net_device *dev);
static void erspan_build_header(struct sk_buff *skb,
- __be32 id, u32 index,
+ u32 id, u32 index,
bool truncate, bool is_ipv4);
static unsigned int ipgre_net_id __read_mostly;
@@ -273,12 +273,12 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
iph = ip_hdr(skb);
ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
- ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET;
+ ver = ershdr->ver;
/* The original GRE header does not have key field,
* Use ERSPAN 10-bit session ID as key.
*/
- tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
+ tpi->key = cpu_to_be32(get_session_id(ershdr));
tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
tpi->flags | TUNNEL_KEY,
iph->saddr, iph->daddr, tpi->key);
@@ -324,14 +324,8 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
if (ver == 1) {
tunnel->index = ntohl(pkt_md->u.index);
} else {
- u16 md2_flags;
- u16 dir, hwid;
-
- md2_flags = ntohs(pkt_md->u.md2.flags);
- dir = (md2_flags & DIR_MASK) >> DIR_OFFSET;
- hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET;
- tunnel->dir = dir;
- tunnel->hwid = hwid;
+ tunnel->dir = pkt_md->u.md2.dir;
+ tunnel->hwid = get_hwid(&pkt_md->u.md2);
}
}
@@ -615,19 +609,14 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
}
if (version == 1) {
- erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
+ erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
ntohl(md->u.index), truncate, true);
} else if (version == 2) {
- u16 md2_flags;
- u8 direction;
- u16 hwid;
-
- md2_flags = ntohs(md->u.md2.flags);
- direction = (md2_flags & DIR_MASK) >> DIR_OFFSET;
- hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET;
-
- erspan_build_header_v2(skb, tunnel_id_to_key32(key->tun_id),
- direction, hwid, truncate, true);
+ erspan_build_header_v2(skb,
+ ntohl(tunnel_id_to_key32(key->tun_id)),
+ md->u.md2.dir,
+ get_hwid(&md->u.md2),
+ truncate, true);
} else {
goto err_free_rt;
}
@@ -733,10 +722,11 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
/* Push ERSPAN header */
if (tunnel->erspan_ver == 1)
- erspan_build_header(skb, tunnel->parms.o_key, tunnel->index,
+ erspan_build_header(skb, ntohl(tunnel->parms.o_key),
+ tunnel->index,
truncate, true);
else
- erspan_build_header_v2(skb, tunnel->parms.o_key,
+ erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
tunnel->dir, tunnel->hwid,
truncate, true);
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index a88480193d77..05f070e123e4 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -513,8 +513,8 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
ipv6h = ipv6_hdr(skb);
ershdr = (struct erspan_base_hdr *)skb->data;
- ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET;
- tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
+ ver = ershdr->ver;
+ tpi->key = cpu_to_be32(get_session_id(ershdr));
tunnel = ip6gre_tunnel_lookup(skb->dev,
&ipv6h->saddr, &ipv6h->daddr, tpi->key,
@@ -565,14 +565,8 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
if (ver == 1) {
tunnel->parms.index = ntohl(pkt_md->u.index);
} else {
- u16 md2_flags;
- u16 dir, hwid;
-
- md2_flags = ntohs(pkt_md->u.md2.flags);
- dir = (md2_flags & DIR_MASK) >> DIR_OFFSET;
- hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET;
- tunnel->parms.dir = dir;
- tunnel->parms.hwid = hwid;
+ tunnel->parms.dir = pkt_md->u.md2.dir;
+ tunnel->parms.hwid = get_hwid(&pkt_md->u.md2);
}
ip6_tnl_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
@@ -925,6 +919,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
struct ip_tunnel_info *tun_info;
const struct ip_tunnel_key *key;
struct erspan_metadata *md;
+ __be32 tun_id;
tun_info = skb_tunnel_info(skb);
if (unlikely(!tun_info ||
@@ -944,23 +939,18 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
if (!md)
goto tx_err;
+ tun_id = tunnel_id_to_key32(key->tun_id);
if (md->version == 1) {
erspan_build_header(skb,
- tunnel_id_to_key32(key->tun_id),
+ ntohl(tun_id),
ntohl(md->u.index), truncate,
false);
} else if (md->version == 2) {
- u16 md2_flags;
- u16 dir, hwid;
-
- md2_flags = ntohs(md->u.md2.flags);
- dir = (md2_flags & DIR_MASK) >> DIR_OFFSET;
- hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET;
-
erspan_build_header_v2(skb,
- tunnel_id_to_key32(key->tun_id),
- dir, hwid, truncate,
- false);
+ ntohl(tun_id),
+ md->u.md2.dir,
+ get_hwid(&md->u.md2),
+ truncate, false);
}
} else {
switch (skb->protocol) {
@@ -982,11 +972,11 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
}
if (t->parms.erspan_ver == 1)
- erspan_build_header(skb, t->parms.o_key,
+ erspan_build_header(skb, ntohl(t->parms.o_key),
t->parms.index,
truncate, false);
else
- erspan_build_header_v2(skb, t->parms.o_key,
+ erspan_build_header_v2(skb, ntohl(t->parms.o_key),
t->parms.dir,
t->parms.hwid,
truncate, false);
--
2.7.4
next prev parent reply other threads:[~2018-01-25 21:20 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-25 21:20 [PATCHv6 net-next 0/3] net: erspan: add support for openvswitch William Tu
2018-01-25 21:20 ` William Tu [this message]
2018-01-26 2:35 ` [PATCHv6 net-next 1/3] net: erspan: use bitfield instead of mask and offset Pravin Shelar
2018-01-25 21:20 ` [PATCHv6 net-next 2/3] net: erspan: create erspan metadata uapi header William Tu
2018-01-26 2:35 ` Pravin Shelar
2018-01-25 21:20 ` [PATCHv6 net-next 3/3] openvswitch: add erspan version I and II support William Tu
2018-01-26 2:35 ` Pravin Shelar
2018-01-26 2:40 ` [PATCHv6 net-next 0/3] net: erspan: add support for openvswitch David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1516915211-5869-2-git-send-email-u9012063@gmail.com \
--to=u9012063@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pshelar@ovn.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.