Skip to content

Commit

Permalink
Merge branch 'flow_dissector-fixes-and-improvements'
Browse files Browse the repository at this point in the history
Alexander Duyck says:

====================
Flow dissector fixes and improvements

This patch series is meant to fix and/or improve a number of items within
the flow dissector code.  The main change out of all of this is that IPv4
and IPv6 fragmentation should now be handled better than it was.  As a
result we should see an improvement when handling things like IP fragment
reassembly as the skbs should now only have header data in the linear
portion of the buffer while the fragments will only hold payload data.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 24, 2016
2 parents f993604 + d975ddd commit d3ffa7a
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 20 deletions.
45 changes: 26 additions & 19 deletions net/core/flow_dissector.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,16 @@ bool __skb_flow_dissect(const struct sk_buff *skb,

ip_proto = iph->protocol;

if (!dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_IPV4_ADDRS))
break;
if (dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
key_addrs = skb_flow_dissector_target(flow_dissector,
FLOW_DISSECTOR_KEY_IPV4_ADDRS,
target_container);

key_addrs = skb_flow_dissector_target(flow_dissector,
FLOW_DISSECTOR_KEY_IPV4_ADDRS, target_container);
memcpy(&key_addrs->v4addrs, &iph->saddr,
sizeof(key_addrs->v4addrs));
key_control->addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
memcpy(&key_addrs->v4addrs, &iph->saddr,
sizeof(key_addrs->v4addrs));
key_control->addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
}

if (ip_is_fragment(iph)) {
key_control->flags |= FLOW_DIS_IS_FRAGMENT;
Expand Down Expand Up @@ -219,13 +220,12 @@ bool __skb_flow_dissect(const struct sk_buff *skb,

if (dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
struct flow_dissector_key_ipv6_addrs *key_ipv6_addrs;

key_ipv6_addrs = skb_flow_dissector_target(flow_dissector,
FLOW_DISSECTOR_KEY_IPV6_ADDRS,
target_container);
key_addrs = skb_flow_dissector_target(flow_dissector,
FLOW_DISSECTOR_KEY_IPV6_ADDRS,
target_container);

memcpy(key_ipv6_addrs, &iph->saddr, sizeof(*key_ipv6_addrs));
memcpy(&key_addrs->v6addrs, &iph->saddr,
sizeof(key_addrs->v6addrs));
key_control->addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
}

Expand Down Expand Up @@ -339,8 +339,11 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
}

case htons(ETH_P_FCOE):
key_control->thoff = (u16)(nhoff + FCOE_HEADER_LEN);
/* fall through */
if ((hlen - nhoff) < FCOE_HEADER_LEN)
goto out_bad;

nhoff += FCOE_HEADER_LEN;
goto out_good;
default:
goto out_bad;
}
Expand Down Expand Up @@ -447,13 +450,12 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
key_control->flags |= FLOW_DIS_IS_FRAGMENT;

nhoff += sizeof(_fh);
ip_proto = fh->nexthdr;

if (!(fh->frag_off & htons(IP6_OFFSET))) {
key_control->flags |= FLOW_DIS_FIRST_FRAG;
if (flags & FLOW_DISSECTOR_F_PARSE_1ST_FRAG) {
ip_proto = fh->nexthdr;
if (flags & FLOW_DISSECTOR_F_PARSE_1ST_FRAG)
goto ip_proto_again;
}
}
goto out_good;
}
Expand Down Expand Up @@ -740,6 +742,11 @@ u32 __skb_get_poff(const struct sk_buff *skb, void *data,
{
u32 poff = keys->control.thoff;

/* skip L4 headers for fragments after the first */
if ((keys->control.flags & FLOW_DIS_IS_FRAGMENT) &&
!(keys->control.flags & FLOW_DIS_FIRST_FRAG))
return poff;

switch (keys->basic.ip_proto) {
case IPPROTO_TCP: {
/* access doff as u8 to avoid unaligned access */
Expand Down
3 changes: 2 additions & 1 deletion net/ethernet/eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ EXPORT_SYMBOL(eth_header);
*/
u32 eth_get_headlen(void *data, unsigned int len)
{
const unsigned int flags = FLOW_DISSECTOR_F_PARSE_1ST_FRAG;
const struct ethhdr *eth = (const struct ethhdr *)data;
struct flow_keys keys;

Expand All @@ -134,7 +135,7 @@ u32 eth_get_headlen(void *data, unsigned int len)

/* parse any remaining L2/L3 headers, check for L4 */
if (!skb_flow_dissect_flow_keys_buf(&keys, data, eth->h_proto,
sizeof(*eth), len, 0))
sizeof(*eth), len, flags))
return max_t(u32, keys.control.thoff, sizeof(*eth));

/* parse for any L4 headers */
Expand Down

0 comments on commit d3ffa7a

Please sign in to comment.