@@ -19,7 +19,8 @@ int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
void *ife_tlv_meta_next(void *skbdata);
struct ethhdr *ife_packet_info_pack(struct sk_buff *skb, int orig_size,
- int in_ifindex, int out_ifindex);
+ int in_ifindex, int out_ifindex,
+ u32 sampler_id, u32 seq);
#else
@@ -52,7 +53,7 @@ static inline void *ife_tlv_meta_next(void *skbdata)
static inline struct ethhdr *
ife_packet_info_pack(struct sk_buff *skb, int orig_size, int in_ifindex,
- int out_ifindex)
+ int out_ifindex, u32 sampler_id, u32 seq)
{
return NULL;
}
@@ -14,9 +14,13 @@ struct tcf_sample {
u8 eth_dst[ETH_ALEN];
u8 eth_src[ETH_ALEN];
u16 eth_type;
+ u32 sampler_id;
+ u32 seq;
struct list_head tcfm_list;
};
#define to_sample(a) ((struct tcf_sample *)a)
+#define TC_SAMPLE_SW_ID(id) ((id << 1) + 0)
+#define TC_SAMPLE_HW_ID(id) ((id << 1) + 1)
static inline bool is_tcf_sample(const struct tc_action *a)
{
@@ -62,4 +66,9 @@ static inline void tcf_sample_eth_src_addr(const struct tc_action *a, u8 *src)
ether_addr_copy(src, to_sample(a)->eth_src);
}
+static inline u32 tcf_sample_sampler_id(const struct tc_action *a)
+{
+ return to_sample(a)->sampler_id;
+}
+
#endif /* __NET_TC_SAMPLE_H */
@@ -13,6 +13,8 @@ enum {
IFE_META_OUT_IFINDEX,
IFE_META_ORIGSIZE,
IFE_META_SIZE,
+ IFE_META_SAMPLER_ID,
+ IFE_META_SEQ,
__IFE_META_MAX
};
@@ -139,7 +139,8 @@ int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen, const void *dval)
EXPORT_SYMBOL_GPL(ife_tlv_meta_encode);
struct ethhdr *ife_packet_info_pack(struct sk_buff *skb, int orig_size,
- int in_ifindex, int out_ifindex)
+ int in_ifindex, int out_ifindex,
+ u32 sampler_id, u32 seq)
{
int curr_size;
void *ifetlv;
@@ -148,7 +149,9 @@ struct ethhdr *ife_packet_info_pack(struct sk_buff *skb, int orig_size,
curr_size = skb->len;
metalen = nla_total_size(sizeof(orig_size)) +
- nla_total_size(sizeof(curr_size));
+ nla_total_size(sizeof(curr_size)) +
+ nla_total_size(sizeof(sampler_id)) +
+ nla_total_size(sizeof(seq));
if (in_ifindex)
metalen += nla_total_size(sizeof(in_ifindex));
@@ -159,6 +162,8 @@ struct ethhdr *ife_packet_info_pack(struct sk_buff *skb, int orig_size,
out_ifindex = htonl(out_ifindex);
orig_size = htonl(orig_size);
curr_size = htonl(curr_size);
+ sampler_id = htonl(sampler_id);
+ seq = htonl(seq);
ifetlv = ife_encode(skb, metalen);
if (!ifetlv)
@@ -179,6 +184,11 @@ struct ethhdr *ife_packet_info_pack(struct sk_buff *skb, int orig_size,
ifetlv += ife_tlv_meta_encode(ifetlv, IFE_META_SIZE,
sizeof(curr_size), &curr_size);
+ ifetlv += ife_tlv_meta_encode(ifetlv, IFE_META_SAMPLER_ID,
+ sizeof(sampler_id), &sampler_id);
+
+ ifetlv += ife_tlv_meta_encode(ifetlv, IFE_META_SEQ, sizeof(seq), &seq);
+
return (struct ethhdr *) skb->data;
}
EXPORT_SYMBOL(ife_packet_info_pack);
@@ -27,6 +27,7 @@
#define SAMPLE_TAB_MASK 7
static int sample_net_id;
+static u32 samplers;
static struct tc_action_ops act_sample_ops;
static const struct nla_policy sample_policy[TCA_SAMPLE_MAX + 1] = {
@@ -77,6 +78,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
s->rate = nla_get_u32(tb[TCA_SAMPLE_RATE]);
s->mark = nla_get_u32(tb[TCA_SAMPLE_MARK]);
s->eth_type = nla_get_u16(tb[TCA_SAMPLE_ETH_TYPE]);
+ s->sampler_id = samplers++;
s->truncate = tb[TCA_SAMPLE_TRUNC_SIZE];
if (tb[TCA_SAMPLE_TRUNC_SIZE])
@@ -119,6 +121,7 @@ static int tcf_sample(struct sk_buff *skb, const struct tc_action *a,
struct tcf_sample *s = to_sample(a);
static struct ethhdr *ethhdr;
struct sk_buff *skb2;
+ u32 sampler_id;
int orig_size;
int retval;
u32 at;
@@ -145,8 +148,12 @@ static int tcf_sample(struct sk_buff *skb, const struct tc_action *a,
skb_push(skb2, skb2->mac_len);
orig_size = skb->len + skb->dev->hard_header_len;
+ sampler_id = TC_SAMPLE_SW_ID(s->sampler_id);
+
ethhdr = ife_packet_info_pack(skb2, orig_size,
- skb->dev->ifindex, 0);
+ skb->dev->ifindex, 0,
+ sampler_id, s->seq++);
+
if (!ethhdr)
goto out;
@@ -267,6 +274,7 @@ static struct pernet_operations sample_net_ops = {
static int __init sample_init_module(void)
{
+ samplers = 0;
return tcf_register_action(&act_sample_ops, &sample_net_ops);
}