ebtables: Allow filtering of hardware accelerated vlan frames.
An upcoming commit will allow packets with hardware vlan acceleration information to be passed though more parts of the network stack, including packets trunked through the bridge. This adds support for matching and filtering those packets through ebtables. Signed-off-by: Jesse Gross <jesse@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
53c90536e9
commit
13937911f9
|
@ -64,22 +64,24 @@ static int brnf_filter_pppoe_tagged __read_mostly = 0;
|
||||||
|
|
||||||
static inline __be16 vlan_proto(const struct sk_buff *skb)
|
static inline __be16 vlan_proto(const struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
|
if (vlan_tx_tag_present(skb))
|
||||||
|
return skb->protocol;
|
||||||
|
else if (skb->protocol == htons(ETH_P_8021Q))
|
||||||
|
return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IS_VLAN_IP(skb) \
|
#define IS_VLAN_IP(skb) \
|
||||||
(skb->protocol == htons(ETH_P_8021Q) && \
|
(vlan_proto(skb) == htons(ETH_P_IP) && \
|
||||||
vlan_proto(skb) == htons(ETH_P_IP) && \
|
|
||||||
brnf_filter_vlan_tagged)
|
brnf_filter_vlan_tagged)
|
||||||
|
|
||||||
#define IS_VLAN_IPV6(skb) \
|
#define IS_VLAN_IPV6(skb) \
|
||||||
(skb->protocol == htons(ETH_P_8021Q) && \
|
(vlan_proto(skb) == htons(ETH_P_IPV6) && \
|
||||||
vlan_proto(skb) == htons(ETH_P_IPV6) &&\
|
|
||||||
brnf_filter_vlan_tagged)
|
brnf_filter_vlan_tagged)
|
||||||
|
|
||||||
#define IS_VLAN_ARP(skb) \
|
#define IS_VLAN_ARP(skb) \
|
||||||
(skb->protocol == htons(ETH_P_8021Q) && \
|
(vlan_proto(skb) == htons(ETH_P_ARP) && \
|
||||||
vlan_proto(skb) == htons(ETH_P_ARP) && \
|
|
||||||
brnf_filter_vlan_tagged)
|
brnf_filter_vlan_tagged)
|
||||||
|
|
||||||
static inline __be16 pppoe_proto(const struct sk_buff *skb)
|
static inline __be16 pppoe_proto(const struct sk_buff *skb)
|
||||||
|
|
|
@ -39,8 +39,6 @@ static bool
|
||||||
ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||||
{
|
{
|
||||||
const struct ebt_vlan_info *info = par->matchinfo;
|
const struct ebt_vlan_info *info = par->matchinfo;
|
||||||
const struct vlan_hdr *fp;
|
|
||||||
struct vlan_hdr _frame;
|
|
||||||
|
|
||||||
unsigned short TCI; /* Whole TCI, given from parsed frame */
|
unsigned short TCI; /* Whole TCI, given from parsed frame */
|
||||||
unsigned short id; /* VLAN ID, given from frame TCI */
|
unsigned short id; /* VLAN ID, given from frame TCI */
|
||||||
|
@ -48,9 +46,20 @@ ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||||
/* VLAN encapsulated Type/Length field, given from orig frame */
|
/* VLAN encapsulated Type/Length field, given from orig frame */
|
||||||
__be16 encap;
|
__be16 encap;
|
||||||
|
|
||||||
fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
|
if (vlan_tx_tag_present(skb)) {
|
||||||
if (fp == NULL)
|
TCI = vlan_tx_tag_get(skb);
|
||||||
return false;
|
encap = skb->protocol;
|
||||||
|
} else {
|
||||||
|
const struct vlan_hdr *fp;
|
||||||
|
struct vlan_hdr _frame;
|
||||||
|
|
||||||
|
fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
|
||||||
|
if (fp == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TCI = ntohs(fp->h_vlan_TCI);
|
||||||
|
encap = fp->h_vlan_encapsulated_proto;
|
||||||
|
}
|
||||||
|
|
||||||
/* Tag Control Information (TCI) consists of the following elements:
|
/* Tag Control Information (TCI) consists of the following elements:
|
||||||
* - User_priority. The user_priority field is three bits in length,
|
* - User_priority. The user_priority field is three bits in length,
|
||||||
|
@ -59,10 +68,8 @@ ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||||
* (CFI) is a single bit flag value. Currently ignored.
|
* (CFI) is a single bit flag value. Currently ignored.
|
||||||
* - VLAN Identifier (VID). The VID is encoded as
|
* - VLAN Identifier (VID). The VID is encoded as
|
||||||
* an unsigned binary number. */
|
* an unsigned binary number. */
|
||||||
TCI = ntohs(fp->h_vlan_TCI);
|
|
||||||
id = TCI & VLAN_VID_MASK;
|
id = TCI & VLAN_VID_MASK;
|
||||||
prio = (TCI >> 13) & 0x7;
|
prio = (TCI >> 13) & 0x7;
|
||||||
encap = fp->h_vlan_encapsulated_proto;
|
|
||||||
|
|
||||||
/* Checking VLAN Identifier (VID) */
|
/* Checking VLAN Identifier (VID) */
|
||||||
if (GET_BITMASK(EBT_VLAN_ID))
|
if (GET_BITMASK(EBT_VLAN_ID))
|
||||||
|
|
|
@ -124,16 +124,23 @@ ebt_dev_check(const char *entry, const struct net_device *device)
|
||||||
#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
|
#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
|
||||||
/* process standard matches */
|
/* process standard matches */
|
||||||
static inline int
|
static inline int
|
||||||
ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
|
ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
|
||||||
const struct net_device *in, const struct net_device *out)
|
const struct net_device *in, const struct net_device *out)
|
||||||
{
|
{
|
||||||
|
const struct ethhdr *h = eth_hdr(skb);
|
||||||
|
__be16 ethproto;
|
||||||
int verdict, i;
|
int verdict, i;
|
||||||
|
|
||||||
|
if (vlan_tx_tag_present(skb))
|
||||||
|
ethproto = htons(ETH_P_8021Q);
|
||||||
|
else
|
||||||
|
ethproto = h->h_proto;
|
||||||
|
|
||||||
if (e->bitmask & EBT_802_3) {
|
if (e->bitmask & EBT_802_3) {
|
||||||
if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
|
if (FWINV2(ntohs(ethproto) >= 1536, EBT_IPROTO))
|
||||||
return 1;
|
return 1;
|
||||||
} else if (!(e->bitmask & EBT_NOPROTO) &&
|
} else if (!(e->bitmask & EBT_NOPROTO) &&
|
||||||
FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
|
FWINV2(e->ethproto != ethproto, EBT_IPROTO))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
|
if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
|
||||||
|
@ -213,7 +220,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
|
||||||
base = private->entries;
|
base = private->entries;
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < nentries) {
|
while (i < nentries) {
|
||||||
if (ebt_basic_match(point, eth_hdr(skb), in, out))
|
if (ebt_basic_match(point, skb, in, out))
|
||||||
goto letscontinue;
|
goto letscontinue;
|
||||||
|
|
||||||
if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0)
|
if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0)
|
||||||
|
|
Loading…
Reference in New Issue