* ppp0..9.
*
* NOTE: Certain meta values depend on other subsystems and are
- * only available if that subsytem is enabled in the kernel.
+ * only available if that subsystem is enabled in the kernel.
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/skbuff.h>
#include <linux/random.h>
+#include <linux/if_vlan.h>
#include <linux/tc_ematch/tc_em_meta.h>
#include <net/dst.h>
#include <net/route.h>
*err = var_dev(skb->dev, dst);
}
+/**************************************************************************
+ * vlan tag
+ **************************************************************************/
+
+META_COLLECTOR(int_vlan_tag)
+{
+ unsigned short uninitialized_var(tag);
+ if (vlan_get_tag(skb, &tag) < 0)
+ *err = -1;
+ else
+ dst->value = tag;
+}
+
+
+
/**************************************************************************
* skb attributes
**************************************************************************/
META_COLLECTOR(int_rtiif)
{
- if (unlikely(skb->dst == NULL))
+ if (unlikely(skb->rtable == NULL))
*err = -1;
else
- dst->value = ((struct rtable*) skb->dst)->fl.iif;
+ dst->value = skb->rtable->fl.iif;
}
/**************************************************************************
[META_ID(SK_SNDTIMEO)] = META_FUNC(int_sk_sndtimeo),
[META_ID(SK_SENDMSG_OFF)] = META_FUNC(int_sk_sendmsg_off),
[META_ID(SK_WRITE_PENDING)] = META_FUNC(int_sk_write_pend),
+ [META_ID(VLAN_TAG)] = META_FUNC(int_vlan_tag),
}
};
return r;
}
-static int meta_var_change(struct meta_value *dst, struct rtattr *rta)
+static int meta_var_change(struct meta_value *dst, struct nlattr *nla)
{
- int len = RTA_PAYLOAD(rta);
+ int len = nla_len(nla);
- dst->val = (unsigned long)kmemdup(RTA_DATA(rta), len, GFP_KERNEL);
+ dst->val = (unsigned long)kmemdup(nla_data(nla), len, GFP_KERNEL);
if (dst->val == 0UL)
return -ENOMEM;
dst->len = len;
static int meta_var_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
{
if (v->val && v->len)
- RTA_PUT(skb, tlv, v->len, (void *) v->val);
+ NLA_PUT(skb, tlv, v->len, (void *) v->val);
return 0;
-rtattr_failure:
+nla_put_failure:
return -1;
}
return 1;
}
-static int meta_int_change(struct meta_value *dst, struct rtattr *rta)
+static int meta_int_change(struct meta_value *dst, struct nlattr *nla)
{
- if (RTA_PAYLOAD(rta) >= sizeof(unsigned long)) {
- dst->val = *(unsigned long *) RTA_DATA(rta);
+ if (nla_len(nla) >= sizeof(unsigned long)) {
+ dst->val = *(unsigned long *) nla_data(nla);
dst->len = sizeof(unsigned long);
- } else if (RTA_PAYLOAD(rta) == sizeof(u32)) {
- dst->val = *(u32 *) RTA_DATA(rta);
+ } else if (nla_len(nla) == sizeof(u32)) {
+ dst->val = nla_get_u32(nla);
dst->len = sizeof(u32);
} else
return -EINVAL;
static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
{
if (v->len == sizeof(unsigned long))
- RTA_PUT(skb, tlv, sizeof(unsigned long), &v->val);
+ NLA_PUT(skb, tlv, sizeof(unsigned long), &v->val);
else if (v->len == sizeof(u32)) {
- u32 d = v->val;
- RTA_PUT(skb, tlv, sizeof(d), &d);
+ NLA_PUT_U32(skb, tlv, v->val);
}
return 0;
-rtattr_failure:
+nla_put_failure:
return -1;
}
{
void (*destroy)(struct meta_value *);
int (*compare)(struct meta_obj *, struct meta_obj *);
- int (*change)(struct meta_value *, struct rtattr *);
+ int (*change)(struct meta_value *, struct nlattr *);
void (*apply_extras)(struct meta_value *, struct meta_obj *);
int (*dump)(struct sk_buff *, struct meta_value *, int);
};
* Core
**************************************************************************/
-static inline int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info,
- struct meta_value *v, struct meta_obj *dst)
+static int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info,
+ struct meta_value *v, struct meta_obj *dst)
{
int err = 0;
return 0;
}
-static inline void meta_delete(struct meta_match *meta)
+static void meta_delete(struct meta_match *meta)
{
- struct meta_type_ops *ops = meta_type_ops(&meta->lvalue);
+ if (meta) {
+ struct meta_type_ops *ops = meta_type_ops(&meta->lvalue);
- if (ops && ops->destroy) {
- ops->destroy(&meta->lvalue);
- ops->destroy(&meta->rvalue);
+ if (ops && ops->destroy) {
+ ops->destroy(&meta->lvalue);
+ ops->destroy(&meta->rvalue);
+ }
}
kfree(meta);
}
-static inline int meta_change_data(struct meta_value *dst, struct rtattr *rta)
+static inline int meta_change_data(struct meta_value *dst, struct nlattr *nla)
{
- if (rta) {
- if (RTA_PAYLOAD(rta) == 0)
+ if (nla) {
+ if (nla_len(nla) == 0)
return -EINVAL;
- return meta_type_ops(dst)->change(dst, rta);
+ return meta_type_ops(dst)->change(dst, nla);
}
return 0;
return (!meta_id(val) || meta_ops(val)->get);
}
+static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = {
+ [TCA_EM_META_HDR] = { .len = sizeof(struct tcf_meta_hdr) },
+};
+
static int em_meta_change(struct tcf_proto *tp, void *data, int len,
struct tcf_ematch *m)
{
- int err = -EINVAL;
- struct rtattr *tb[TCA_EM_META_MAX];
+ int err;
+ struct nlattr *tb[TCA_EM_META_MAX + 1];
struct tcf_meta_hdr *hdr;
struct meta_match *meta = NULL;
- if (rtattr_parse(tb, TCA_EM_META_MAX, data, len) < 0)
+ err = nla_parse(tb, TCA_EM_META_MAX, data, len, meta_policy);
+ if (err < 0)
goto errout;
- if (tb[TCA_EM_META_HDR-1] == NULL ||
- RTA_PAYLOAD(tb[TCA_EM_META_HDR-1]) < sizeof(*hdr))
+ err = -EINVAL;
+ if (tb[TCA_EM_META_HDR] == NULL)
goto errout;
- hdr = RTA_DATA(tb[TCA_EM_META_HDR-1]);
+ hdr = nla_data(tb[TCA_EM_META_HDR]);
if (TCF_META_TYPE(hdr->left.kind) != TCF_META_TYPE(hdr->right.kind) ||
TCF_META_TYPE(hdr->left.kind) > TCF_META_TYPE_MAX ||
goto errout;
}
- if (meta_change_data(&meta->lvalue, tb[TCA_EM_META_LVALUE-1]) < 0 ||
- meta_change_data(&meta->rvalue, tb[TCA_EM_META_RVALUE-1]) < 0)
+ if (meta_change_data(&meta->lvalue, tb[TCA_EM_META_LVALUE]) < 0 ||
+ meta_change_data(&meta->rvalue, tb[TCA_EM_META_RVALUE]) < 0)
goto errout;
m->datalen = sizeof(*meta);
memcpy(&hdr.left, &meta->lvalue.hdr, sizeof(hdr.left));
memcpy(&hdr.right, &meta->rvalue.hdr, sizeof(hdr.right));
- RTA_PUT(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr);
+ NLA_PUT(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr);
ops = meta_type_ops(&meta->lvalue);
if (ops->dump(skb, &meta->lvalue, TCA_EM_META_LVALUE) < 0 ||
ops->dump(skb, &meta->rvalue, TCA_EM_META_RVALUE) < 0)
- goto rtattr_failure;
+ goto nla_put_failure;
return 0;
-rtattr_failure:
+nla_put_failure:
return -1;
}