#include <net/act_api.h>
#include <net/netlink.h>
-#define L2T(p,L) ((p)->tcfp_R_tab->data[(L)>>(p)->tcfp_R_tab->rate.cell_log])
-#define L2T_P(p,L) ((p)->tcfp_P_tab->data[(L)>>(p)->tcfp_P_tab->rate.cell_log])
+#define L2T(p,L) qdisc_l2t((p)->tcfp_R_tab, L)
+#define L2T_P(p,L) qdisc_l2t((p)->tcfp_P_tab, L)
#define POL_TAB_MASK 15
static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1];
{
struct tcf_common *p;
int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
- struct rtattr *r;
+ struct nlattr *nest;
read_lock_bh(&police_lock);
continue;
a->priv = p;
a->order = index;
- r = (struct rtattr *)skb_tail_pointer(skb);
- RTA_PUT(skb, a->order, 0, NULL);
+ nest = nla_nest_start(skb, a->order);
+ if (nest == NULL)
+ goto nla_put_failure;
if (type == RTM_DELACTION)
err = tcf_action_dump_1(skb, a, 0, 1);
else
err = tcf_action_dump_1(skb, a, 0, 0);
if (err < 0) {
index--;
- nlmsg_trim(skb, r);
+ nla_nest_cancel(skb, nest);
goto done;
}
- r->rta_len = skb_tail_pointer(skb) - (u8 *)r;
+ nla_nest_end(skb, nest);
n_i++;
}
}
cb->args[0] += n_i;
return n_i;
-rtattr_failure:
- nlmsg_trim(skb, r);
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
goto done;
}
return;
}
}
- BUG_TRAP(0);
+ WARN_ON(1);
}
-static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
+static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
+ [TCA_POLICE_RATE] = { .len = TC_RTAB_SIZE },
+ [TCA_POLICE_PEAKRATE] = { .len = TC_RTAB_SIZE },
+ [TCA_POLICE_AVRATE] = { .type = NLA_U32 },
+ [TCA_POLICE_RESULT] = { .type = NLA_U32 },
+};
+
+static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
unsigned h;
int ret = 0, err;
- struct rtattr *tb[TCA_POLICE_MAX];
+ struct nlattr *tb[TCA_POLICE_MAX + 1];
struct tc_police *parm;
struct tcf_police *police;
struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
int size;
- if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
+ if (nla == NULL)
return -EINVAL;
- if (tb[TCA_POLICE_TBF-1] == NULL)
- return -EINVAL;
- size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
- if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
- return -EINVAL;
- parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
+ err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy);
+ if (err < 0)
+ return err;
- if (tb[TCA_POLICE_RESULT-1] != NULL &&
- RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
+ if (tb[TCA_POLICE_TBF] == NULL)
return -EINVAL;
- if (tb[TCA_POLICE_RESULT-1] != NULL &&
- RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
+ size = nla_len(tb[TCA_POLICE_TBF]);
+ if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
return -EINVAL;
+ parm = nla_data(tb[TCA_POLICE_TBF]);
if (parm->index) {
struct tcf_common *pc;
override:
if (parm->rate.rate) {
err = -ENOMEM;
- R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
+ R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
if (R_tab == NULL)
goto failure;
if (parm->peakrate.rate) {
P_tab = qdisc_get_rtab(&parm->peakrate,
- tb[TCA_POLICE_PEAKRATE-1]);
+ tb[TCA_POLICE_PEAKRATE]);
if (P_tab == NULL) {
qdisc_put_rtab(R_tab);
goto failure;
police->tcfp_P_tab = P_tab;
}
- if (tb[TCA_POLICE_RESULT-1])
- police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
+ if (tb[TCA_POLICE_RESULT])
+ police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
police->tcfp_toks = police->tcfp_burst = parm->burst;
police->tcfp_mtu = parm->mtu;
if (police->tcfp_mtu == 0) {
police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
police->tcf_action = parm->action;
- if (tb[TCA_POLICE_AVRATE-1])
- police->tcfp_ewma_rate =
- *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
+ if (tb[TCA_POLICE_AVRATE])
+ police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
if (est)
gen_replace_estimator(&police->tcf_bstats,
&police->tcf_rate_est,
spin_lock(&police->tcf_lock);
- police->tcf_bstats.bytes += skb->len;
+ police->tcf_bstats.bytes += qdisc_pkt_len(skb);
police->tcf_bstats.packets++;
if (police->tcfp_ewma_rate &&
return police->tcf_action;
}
- if (skb->len <= police->tcfp_mtu) {
+ if (qdisc_pkt_len(skb) <= police->tcfp_mtu) {
if (police->tcfp_R_tab == NULL) {
spin_unlock(&police->tcf_lock);
return police->tcfp_result;
ptoks = toks + police->tcfp_ptoks;
if (ptoks > (long)L2T_P(police, police->tcfp_mtu))
ptoks = (long)L2T_P(police, police->tcfp_mtu);
- ptoks -= L2T_P(police, skb->len);
+ ptoks -= L2T_P(police, qdisc_pkt_len(skb));
}
toks += police->tcfp_toks;
if (toks > (long)police->tcfp_burst)
toks = police->tcfp_burst;
- toks -= L2T(police, skb->len);
+ toks -= L2T(police, qdisc_pkt_len(skb));
if ((toks|ptoks) >= 0) {
police->tcfp_t_c = now;
police->tcfp_toks = toks;
opt.peakrate = police->tcfp_P_tab->rate;
else
memset(&opt.peakrate, 0, sizeof(opt.peakrate));
- RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
+ NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
if (police->tcfp_result)
- RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
- &police->tcfp_result);
+ NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result);
if (police->tcfp_ewma_rate)
- RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
+ NLA_PUT_U32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate);
return skb->len;
-rtattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}