mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
Merge branch 'eth_proto_is_802_3'
Alexander Duyck says: ==================== Add eth_proto_is_802_3 to provide improved means of checking Ethertype This patch series implements and makes use of eth_proto_is_802_3(). The idea behind the function is to provide an optimized means of testing to determine if a given Ethertype value is a length or 802.3 protocol number. The standard path for this was to use ntohs(proto) and then perform a comparison. This adds a slight cost as it usually requires either a 16b rotate or byte swap which can cost 1 cycle or more depending on the processor. I had previously addressed this for eth_type_trans, however in doing so I had overlooked checking with sparse and had introduced a couple sparse warnings. The first patch in this series fixes those sparse warnings as well as does some additional optimization for big endian systems. In addition it pushes the code out into a separate function which can then be used in the other patches to reduce the instruction count/processing time in those functions as well. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
76061d99a3
8 changed files with 26 additions and 8 deletions
|
@ -190,6 +190,24 @@ static inline bool is_valid_ether_addr(const u8 *addr)
|
|||
return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_proto_is_802_3 - Determine if a given Ethertype/length is a protocol
|
||||
* @proto: Ethertype/length value to be tested
|
||||
*
|
||||
* Check that the value from the Ethertype/length field is a valid Ethertype.
|
||||
*
|
||||
* Return true if the valid is an 802.3 supported Ethertype.
|
||||
*/
|
||||
static inline bool eth_proto_is_802_3(__be16 proto)
|
||||
{
|
||||
#ifndef __BIG_ENDIAN
|
||||
/* if CPU is little endian mask off bits representing LSB */
|
||||
proto &= htons(0xFF00);
|
||||
#endif
|
||||
/* cast both to u16 and compare since LSB can be ignored */
|
||||
return (__force u16)proto >= (__force u16)htons(ETH_P_802_3_MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_random_addr - Generate software assigned random Ethernet address
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
|
|
|
@ -539,7 +539,7 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb,
|
|||
*/
|
||||
|
||||
proto = vhdr->h_vlan_encapsulated_proto;
|
||||
if (ntohs(proto) >= ETH_P_802_3_MIN) {
|
||||
if (eth_proto_is_802_3(proto)) {
|
||||
skb->protocol = proto;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
|
|||
ethproto = h->h_proto;
|
||||
|
||||
if (e->bitmask & EBT_802_3) {
|
||||
if (FWINV2(ntohs(ethproto) >= ETH_P_802_3_MIN, EBT_IPROTO))
|
||||
if (FWINV2(eth_proto_is_802_3(ethproto), EBT_IPROTO))
|
||||
return 1;
|
||||
} else if (!(e->bitmask & EBT_NOPROTO) &&
|
||||
FWINV2(e->ethproto != ethproto, EBT_IPROTO))
|
||||
|
|
|
@ -179,7 +179,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
|
|||
if (unlikely(netdev_uses_dsa(dev)))
|
||||
return htons(ETH_P_XDSA);
|
||||
|
||||
if (likely((eth->h_proto & htons(0xFF00)) >= htons(ETH_P_802_3_MIN)))
|
||||
if (likely(eth_proto_is_802_3(eth->h_proto)))
|
||||
return eth->h_proto;
|
||||
|
||||
/*
|
||||
|
|
|
@ -98,7 +98,7 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
|
|||
return -ENOMEM;
|
||||
|
||||
eh = (struct ethhdr *)skb->data;
|
||||
if (likely(ntohs(eh->h_proto) >= ETH_P_802_3_MIN))
|
||||
if (likely(eth_proto_is_802_3(eh->h_proto)))
|
||||
skb->protocol = eh->h_proto;
|
||||
else
|
||||
skb->protocol = htons(ETH_P_802_2);
|
||||
|
|
|
@ -545,7 +545,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
|
|||
/* Normally, setting the skb 'protocol' field would be handled by a
|
||||
* call to eth_type_trans(), but it assumes there's a sending
|
||||
* device, which we may not have. */
|
||||
if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
|
||||
if (eth_proto_is_802_3(eth->h_proto))
|
||||
packet->protocol = eth->h_proto;
|
||||
else
|
||||
packet->protocol = htons(ETH_P_802_2);
|
||||
|
|
|
@ -332,7 +332,7 @@ static __be16 parse_ethertype(struct sk_buff *skb)
|
|||
proto = *(__be16 *) skb->data;
|
||||
__skb_pull(skb, sizeof(__be16));
|
||||
|
||||
if (ntohs(proto) >= ETH_P_802_3_MIN)
|
||||
if (eth_proto_is_802_3(proto))
|
||||
return proto;
|
||||
|
||||
if (skb->len < sizeof(struct llc_snap_hdr))
|
||||
|
@ -349,7 +349,7 @@ static __be16 parse_ethertype(struct sk_buff *skb)
|
|||
|
||||
__skb_pull(skb, sizeof(struct llc_snap_hdr));
|
||||
|
||||
if (ntohs(llc->ethertype) >= ETH_P_802_3_MIN)
|
||||
if (eth_proto_is_802_3(llc->ethertype))
|
||||
return llc->ethertype;
|
||||
|
||||
return htons(ETH_P_802_2);
|
||||
|
|
|
@ -816,7 +816,7 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
|||
if (is_mask) {
|
||||
/* Always exact match EtherType. */
|
||||
eth_type = htons(0xffff);
|
||||
} else if (ntohs(eth_type) < ETH_P_802_3_MIN) {
|
||||
} else if (!eth_proto_is_802_3(eth_type)) {
|
||||
OVS_NLERR(log, "EtherType %x is less than min %x",
|
||||
ntohs(eth_type), ETH_P_802_3_MIN);
|
||||
return -EINVAL;
|
||||
|
|
Loading…
Reference in a new issue