#define VLAN_HLEN 4 /* The additional bytes required by VLAN * (in addition to the Ethernet header)
*/ #define VLAN_ETH_HLEN 18 /* Total octets in header. */ #define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */
/* * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan
*/ #define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */ #define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */
#define VLAN_MAX_DEPTH 8 /* Max. number of nested VLAN tags parsed */
/* * struct vlan_hdr - vlan header * @h_vlan_TCI: priority and VLAN ID * @h_vlan_encapsulated_proto: packet type ID or len
*/ struct vlan_hdr {
__be16 h_vlan_TCI;
__be16 h_vlan_encapsulated_proto;
};
/** * struct vlan_ethhdr - vlan ethernet header (ethhdr + vlan_hdr) * @h_dest: destination ethernet address * @h_source: source ethernet address * @h_vlan_proto: ethernet protocol * @h_vlan_TCI: priority and VLAN ID * @h_vlan_encapsulated_proto: packet type ID or len
*/ struct vlan_ethhdr {
struct_group(addrs, unsignedchar h_dest[ETH_ALEN]; unsignedchar h_source[ETH_ALEN];
);
__be16 h_vlan_proto;
__be16 h_vlan_TCI;
__be16 h_vlan_encapsulated_proto;
};
/** * struct vlan_pcpu_stats - VLAN percpu rx/tx stats * @rx_packets: number of received packets * @rx_bytes: number of received bytes * @rx_multicast: number of received multicast packets * @tx_packets: number of transmitted packets * @tx_bytes: number of transmitted bytes * @syncp: synchronization point for 64bit counters * @rx_errors: number of rx errors * @tx_dropped: number of tx drops
*/ struct vlan_pcpu_stats {
u64_stats_t rx_packets;
u64_stats_t rx_bytes;
u64_stats_t rx_multicast;
u64_stats_t tx_packets;
u64_stats_t tx_bytes; struct u64_stats_sync syncp;
u32 rx_errors;
u32 tx_dropped;
};
smp_rmb(); /* coupled with smp_wmb() in vlan_dev_set_egress_priority() */
mp = vlan_dev_priv(dev)->egress_priority_map[(skprio & 0xF)]; while (mp) { if (mp->priority == skprio) { return mp->vlan_qos; /* This should already be shifted * to mask correctly with the
* VLAN's TCI */
}
mp = mp->next;
} return 0;
}
externbool vlan_do_receive(struct sk_buff **skb);
externint vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid); externvoid vlan_vid_del(struct net_device *dev, __be16 proto, u16 vid);
/** * eth_type_vlan - check for valid vlan ether type. * @ethertype: ether type to check * * Returns: true if the ether type is a vlan ether type.
*/ staticinlinebool eth_type_vlan(__be16 ethertype)
{ switch (ethertype) { case htons(ETH_P_8021Q): case htons(ETH_P_8021AD): returntrue; default: returnfalse;
}
}
staticinlinebool vlan_hw_offload_capable(netdev_features_t features,
__be16 proto)
{ if (proto == htons(ETH_P_8021Q) && features & NETIF_F_HW_VLAN_CTAG_TX) returntrue; if (proto == htons(ETH_P_8021AD) && features & NETIF_F_HW_VLAN_STAG_TX) returntrue; returnfalse;
}
/** * __vlan_insert_inner_tag - inner VLAN tag inserting * @skb: skbuff to tag * @vlan_proto: VLAN encapsulation protocol * @vlan_tci: VLAN TCI to insert * @mac_len: MAC header length including outer vlan headers * * Inserts the VLAN tag into @skb as part of the payload at offset mac_len * Does not change skb->protocol so this function can be used during receive. * * Returns: error if skb_cow_head fails.
*/ staticinlineint __vlan_insert_inner_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci, unsignedint mac_len)
{ struct vlan_ethhdr *veth;
if (skb_cow_head(skb, VLAN_HLEN) < 0) return -ENOMEM;
skb_push(skb, VLAN_HLEN);
/* Move the mac header sans proto to the beginning of the new header. */ if (likely(mac_len > ETH_TLEN))
memmove(skb->data, skb->data + VLAN_HLEN, mac_len - ETH_TLEN); if (skb_mac_header_was_set(skb))
skb->mac_header -= VLAN_HLEN;
/* first, the ethernet type */ if (likely(mac_len >= ETH_TLEN)) { /* h_vlan_encapsulated_proto should already be populated, and * skb->data has space for h_vlan_proto
*/
veth->h_vlan_proto = vlan_proto;
} else { /* h_vlan_encapsulated_proto should not be populated, and * skb->data has no space for h_vlan_proto
*/
veth->h_vlan_encapsulated_proto = skb->protocol;
}
/* now, the TCI */
veth->h_vlan_TCI = htons(vlan_tci);
return 0;
}
/** * __vlan_insert_tag - regular VLAN tag inserting * @skb: skbuff to tag * @vlan_proto: VLAN encapsulation protocol * @vlan_tci: VLAN TCI to insert * * Inserts the VLAN tag into @skb as part of the payload * Does not change skb->protocol so this function can be used during receive. * * Returns: error if skb_cow_head fails.
*/ staticinlineint __vlan_insert_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
{ return __vlan_insert_inner_tag(skb, vlan_proto, vlan_tci, ETH_HLEN);
}
/** * vlan_insert_inner_tag - inner VLAN tag inserting * @skb: skbuff to tag * @vlan_proto: VLAN encapsulation protocol * @vlan_tci: VLAN TCI to insert * @mac_len: MAC header length including outer vlan headers * * Inserts the VLAN tag into @skb as part of the payload at offset mac_len * Returns a VLAN tagged skb. This might change skb->head. * * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb. * * Does not change skb->protocol so this function can be used during receive. * * Return: modified @skb on success, NULL on error (@skb is freed).
*/ staticinlinestruct sk_buff *vlan_insert_inner_tag(struct sk_buff *skb,
__be16 vlan_proto,
u16 vlan_tci, unsignedint mac_len)
{ int err;
/** * vlan_insert_tag - regular VLAN tag inserting * @skb: skbuff to tag * @vlan_proto: VLAN encapsulation protocol * @vlan_tci: VLAN TCI to insert * * Inserts the VLAN tag into @skb as part of the payload * Returns a VLAN tagged skb. This might change skb->head. * * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb. * * Does not change skb->protocol so this function can be used during receive. * * Return: modified @skb on success, NULL on error (@skb is freed).
*/ staticinlinestruct sk_buff *vlan_insert_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
{ return vlan_insert_inner_tag(skb, vlan_proto, vlan_tci, ETH_HLEN);
}
/** * vlan_insert_tag_set_proto - regular VLAN tag inserting * @skb: skbuff to tag * @vlan_proto: VLAN encapsulation protocol * @vlan_tci: VLAN TCI to insert * * Inserts the VLAN tag into @skb as part of the payload * Returns a VLAN tagged skb. This might change skb->head. * * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb. * * Return: modified @skb on success, NULL on error (@skb is freed).
*/ staticinlinestruct sk_buff *vlan_insert_tag_set_proto(struct sk_buff *skb,
__be16 vlan_proto,
u16 vlan_tci)
{
skb = vlan_insert_tag(skb, vlan_proto, vlan_tci); if (skb)
skb->protocol = vlan_proto; return skb;
}
/** * __vlan_hwaccel_clear_tag - clear hardware accelerated VLAN info * @skb: skbuff to clear * * Clears the VLAN information from @skb
*/ staticinlinevoid __vlan_hwaccel_clear_tag(struct sk_buff *skb)
{
skb->vlan_all = 0;
}
/** * __vlan_hwaccel_copy_tag - copy hardware accelerated VLAN info from another skb * @dst: skbuff to copy to * @src: skbuff to copy from * * Copies VLAN information from @src to @dst (for branchless code)
*/ staticinlinevoid __vlan_hwaccel_copy_tag(struct sk_buff *dst, conststruct sk_buff *src)
{
dst->vlan_all = src->vlan_all;
}
/* * __vlan_hwaccel_push_inside - pushes vlan tag to the payload * @skb: skbuff to tag * * Pushes the VLAN tag from @skb->vlan_tci inside to the payload. * * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb.
*/ staticinlinestruct sk_buff *__vlan_hwaccel_push_inside(struct sk_buff *skb)
{
skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
skb_vlan_tag_get(skb)); if (likely(skb))
__vlan_hwaccel_clear_tag(skb); return skb;
}
/** * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting * @skb: skbuff to tag * @vlan_proto: VLAN encapsulation protocol * @vlan_tci: VLAN TCI to insert * * Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest
*/ staticinlinevoid __vlan_hwaccel_put_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
{
skb->vlan_proto = vlan_proto;
skb->vlan_tci = vlan_tci;
}
/** * __vlan_get_tag - get the VLAN ID that is part of the payload * @skb: skbuff to query * @vlan_tci: buffer to store value * * Returns: error if the skb is not of VLAN type
*/ staticinlineint __vlan_get_tag(conststruct sk_buff *skb, u16 *vlan_tci)
{ struct vlan_ethhdr *veth = skb_vlan_eth_hdr(skb);
if (!eth_type_vlan(veth->h_vlan_proto)) return -ENODATA;
*vlan_tci = ntohs(veth->h_vlan_TCI); return 0;
}
/** * __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[] * @skb: skbuff to query * @vlan_tci: buffer to store value * * Returns: error if @skb->vlan_tci is not set correctly
*/ staticinlineint __vlan_hwaccel_get_tag(conststruct sk_buff *skb,
u16 *vlan_tci)
{ if (skb_vlan_tag_present(skb)) {
*vlan_tci = skb_vlan_tag_get(skb); return 0;
} else {
*vlan_tci = 0; return -ENODATA;
}
}
/** * vlan_get_tag - get the VLAN ID from the skb * @skb: skbuff to query * @vlan_tci: buffer to store value * * Returns: error if the skb is not VLAN tagged
*/ staticinlineint vlan_get_tag(conststruct sk_buff *skb, u16 *vlan_tci)
{ if (skb->dev->features & NETIF_F_HW_VLAN_CTAG_TX) { return __vlan_hwaccel_get_tag(skb, vlan_tci);
} else { return __vlan_get_tag(skb, vlan_tci);
}
}
/** * __vlan_get_protocol_offset() - get protocol EtherType. * @skb: skbuff to query * @type: first vlan protocol * @mac_offset: MAC offset * @depth: buffer to store length of eth and vlan tags in bytes * * Returns: the EtherType of the packet, regardless of whether it is * vlan encapsulated (normal or hardware accelerated) or not.
*/ staticinline __be16 __vlan_get_protocol_offset(conststruct sk_buff *skb,
__be16 type, int mac_offset, int *depth)
{ unsignedint vlan_depth = skb->mac_len, parse_depth = VLAN_MAX_DEPTH;
/* if type is 802.1Q/AD then the header should already be * present at mac_len - VLAN_HLEN (if mac_len > 0), or at * ETH_HLEN otherwise
*/ if (eth_type_vlan(type)) { if (vlan_depth) { if (WARN_ON(vlan_depth < VLAN_HLEN)) return 0;
vlan_depth -= VLAN_HLEN;
} else {
vlan_depth = ETH_HLEN;
} do { struct vlan_hdr vhdr, *vh;
/** * vlan_get_protocol - get protocol EtherType. * @skb: skbuff to query * * Returns: the EtherType of the packet, regardless of whether it is * vlan encapsulated (normal or hardware accelerated) or not.
*/ staticinline __be16 vlan_get_protocol(conststruct sk_buff *skb)
{ return __vlan_get_protocol(skb, skb->protocol, NULL);
}
/* This version of __vlan_get_protocol() also pulls mac header in skb->head */ staticinline __be16 vlan_get_protocol_and_depth(struct sk_buff *skb,
__be16 type, int *depth)
{ int maclen;
type = __vlan_get_protocol(skb, type, &maclen);
if (type) { if (!pskb_may_pull(skb, maclen))
type = 0; elseif (depth)
*depth = maclen;
} return type;
}
/* A getter for the SKB protocol field which will handle VLAN tags consistently * whether VLAN acceleration is enabled or not.
*/ staticinline __be16 skb_protocol(conststruct sk_buff *skb, bool skip_vlan)
{ if (!skip_vlan) /* VLAN acceleration strips the VLAN header from the skb and * moves it to skb->vlan_proto
*/ return skb_vlan_tag_present(skb) ? skb->vlan_proto : skb->protocol;
/* * Was a VLAN packet, grab the encapsulated protocol, which the layer * three protocols care about.
*/
proto = vhdr->h_vlan_encapsulated_proto; if (eth_proto_is_802_3(proto)) {
skb->protocol = proto; return;
}
rawp = (unsignedshort *)(vhdr + 1); if (*rawp == 0xFFFF) /* * This is a magic hack to spot IPX packets. Older Novell * breaks the protocol design and runs IPX over 802.3 without * an 802.2 LLC layer. We look for FFFF which isn't a used * 802.2 SSAP/DSAP. This won't work for fault tolerant netware * but does for the rest.
*/
skb->protocol = htons(ETH_P_802_3); else /* * Real 802.2 LLC
*/
skb->protocol = htons(ETH_P_802_2);
}
/** * vlan_remove_tag - remove outer VLAN tag from payload * @skb: skbuff to remove tag from * @vlan_tci: buffer to store value * * Expects the skb to contain a VLAN tag in the payload, and to have skb->data * pointing at the MAC header. * * Returns: a new pointer to skb->data, or NULL on failure to pull.
*/ staticinlinevoid *vlan_remove_tag(struct sk_buff *skb, u16 *vlan_tci)
{ struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN);
/** * skb_vlan_tagged - check if skb is vlan tagged. * @skb: skbuff to query * * Returns: true if the skb is tagged, regardless of whether it is hardware * accelerated or not.
*/ staticinlinebool skb_vlan_tagged(conststruct sk_buff *skb)
{ if (!skb_vlan_tag_present(skb) &&
likely(!eth_type_vlan(skb->protocol))) returnfalse;
returntrue;
}
/** * skb_vlan_tagged_multi - check if skb is vlan tagged with multiple headers. * @skb: skbuff to query * * Returns: true if the skb is tagged with multiple vlan headers, regardless * of whether it is hardware accelerated or not.
*/ staticinlinebool skb_vlan_tagged_multi(struct sk_buff *skb)
{
__be16 protocol = skb->protocol;
if (!skb_vlan_tag_present(skb)) { struct vlan_ethhdr *veh;
if (likely(!eth_type_vlan(protocol))) returnfalse;
if (unlikely(!pskb_may_pull(skb, VLAN_ETH_HLEN))) returnfalse;
/** * vlan_features_check - drop unsafe features for skb with multiple tags. * @skb: skbuff to query * @features: features to be checked * * Returns: features without unsafe ones if the skb has multiple tags.
*/ staticinline netdev_features_t vlan_features_check(struct sk_buff *skb,
netdev_features_t features)
{ if (skb_vlan_tagged_multi(skb)) { /* In the case of multi-tagged packets, use a direct mask * instead of using netdev_interesect_features(), to make * sure that only devices supporting NETIF_F_HW_CSUM will * have checksum offloading support.
*/
features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_STAG_TX;
}
return features;
}
/** * compare_vlan_header - Compare two vlan headers * @h1: Pointer to vlan header * @h2: Pointer to vlan header * * Compare two vlan headers. * * Please note that alignment of h1 & h2 are only guaranteed to be 16 bits. * * Return: 0 if equal, arbitrary non-zero value if not equal.
*/ staticinlineunsignedlong compare_vlan_header(conststruct vlan_hdr *h1, conststruct vlan_hdr *h2)
{ #ifdefined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) return *(u32 *)h1 ^ *(u32 *)h2; #else return ((__force u32)h1->h_vlan_TCI ^ (__force u32)h2->h_vlan_TCI) |
((__force u32)h1->h_vlan_encapsulated_proto ^
(__force u32)h2->h_vlan_encapsulated_proto); #endif
} #endif/* !(_LINUX_IF_VLAN_H_) */
Messung V0.5
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.