Ejemplo n.º 1
0
static int fw_msg_parser(struct rtnl_cls *cls)
{
	struct rtnl_fw *f = rtnl_cls_data(cls);
	struct nlattr *tb[TCA_FW_MAX + 1];
	int err;

	err = tca_parse(tb, TCA_FW_MAX, (struct rtnl_tca *) cls, fw_policy);
	if (err < 0)
		return err;

	if (tb[TCA_FW_CLASSID]) {
		f->cf_classid = nla_get_u32(tb[TCA_FW_CLASSID]);
		f->cf_mask |= FW_ATTR_CLASSID;
	}

	if (tb[TCA_FW_ACT]) {
		f->cf_act = nl_data_alloc_attr(tb[TCA_FW_ACT]);
		if (!f->cf_act)
			return -NLE_NOMEM;
		f->cf_mask |= FW_ATTR_ACTION;
	}

	if (tb[TCA_FW_POLICE]) {
		f->cf_police = nl_data_alloc_attr(tb[TCA_FW_POLICE]);
		if (!f->cf_police)
			return -NLE_NOMEM;
		f->cf_mask |= FW_ATTR_POLICE;
	}

	if (tb[TCA_FW_INDEV]) {
		nla_strlcpy(f->cf_indev, tb[TCA_FW_INDEV], IFNAMSIZ);
		f->cf_mask |= FW_ATTR_INDEV;
	}

	return 0;
}
Ejemplo n.º 2
0
int tca_msg_parser(struct nlmsghdr *n, struct rtnl_tc *g)
{
	struct nlattr *tb[TCA_MAX + 1];
	struct tcmsg *tm;
	int err;

	err = nlmsg_parse(n, sizeof(*tm), tb, TCA_MAX, tc_policy);
	if (err < 0)
		return err;

	if (tb[TCA_KIND] == NULL)
		return -NLE_MISSING_ATTR;

	nla_strlcpy(g->tc_kind, tb[TCA_KIND], TCKINDSIZ);

	tm = nlmsg_data(n);
	g->tc_family  = tm->tcm_family;
	g->tc_ifindex = tm->tcm_ifindex;
	g->tc_handle  = tm->tcm_handle;
	g->tc_parent  = tm->tcm_parent;
	g->tc_info    = tm->tcm_info;

	g->ce_mask = (TCA_ATTR_FAMILY | TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE |
		      TCA_ATTR_PARENT | TCA_ATTR_INFO | TCA_ATTR_KIND);

	if (tb[TCA_OPTIONS]) {
		g->tc_opts = nl_data_alloc_attr(tb[TCA_OPTIONS]);
		if (!g->tc_opts)
			return -NLE_NOMEM;
		g->ce_mask |= TCA_ATTR_OPTS;
	}
	

	if (tb[TCA_STATS2]) {
		struct nlattr *tbs[TCA_STATS_MAX + 1];

		err = nla_parse_nested(tbs, TCA_STATS_MAX, tb[TCA_STATS2],
				       tc_stats2_policy);
		if (err < 0)
			return err;

		if (tbs[TCA_STATS_BASIC]) {
			struct gnet_stats_basic *bs;
			
			bs = nla_data(tbs[TCA_STATS_BASIC]);
			g->tc_stats[RTNL_TC_BYTES]	= bs->bytes;
			g->tc_stats[RTNL_TC_PACKETS]	= bs->packets;
		}

		if (tbs[TCA_STATS_RATE_EST]) {
			struct gnet_stats_rate_est *re;

			re = nla_data(tbs[TCA_STATS_RATE_EST]);
			g->tc_stats[RTNL_TC_RATE_BPS]	= re->bps;
			g->tc_stats[RTNL_TC_RATE_PPS]	= re->pps;
		}
		
		if (tbs[TCA_STATS_QUEUE]) {
			struct gnet_stats_queue *q;

			q = nla_data(tbs[TCA_STATS_QUEUE]);
			g->tc_stats[RTNL_TC_QLEN]	= q->qlen;
			g->tc_stats[RTNL_TC_BACKLOG]	= q->backlog;
			g->tc_stats[RTNL_TC_DROPS]	= q->drops;
			g->tc_stats[RTNL_TC_REQUEUES]	= q->requeues;
			g->tc_stats[RTNL_TC_OVERLIMITS]	= q->overlimits;
		}

		g->ce_mask |= TCA_ATTR_STATS;
		
		if (tbs[TCA_STATS_APP]) {
			g->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]);
			if (g->tc_xstats == NULL)
				return -NLE_NOMEM;
		} else
			goto compat_xstats;
	} else {
		if (tb[TCA_STATS]) {
			struct tc_stats *st = nla_data(tb[TCA_STATS]);

			g->tc_stats[RTNL_TC_BYTES]	= st->bytes;
			g->tc_stats[RTNL_TC_PACKETS]	= st->packets;
			g->tc_stats[RTNL_TC_RATE_BPS]	= st->bps;
			g->tc_stats[RTNL_TC_RATE_PPS]	= st->pps;
			g->tc_stats[RTNL_TC_QLEN]	= st->qlen;
			g->tc_stats[RTNL_TC_BACKLOG]	= st->backlog;
			g->tc_stats[RTNL_TC_DROPS]	= st->drops;
			g->tc_stats[RTNL_TC_OVERLIMITS]	= st->overlimits;

			g->ce_mask |= TCA_ATTR_STATS;
		}

compat_xstats:
		if (tb[TCA_XSTATS]) {
			g->tc_xstats = nl_data_alloc_attr(tb[TCA_XSTATS]);
			if (g->tc_xstats == NULL)
				return -NLE_NOMEM;
			g->ce_mask |= TCA_ATTR_XSTATS;
		}
	}


	return 0;
}
Ejemplo n.º 3
0
Archivo: tc.c Proyecto: acooks/libnl
int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc)
{
	struct nl_cache *link_cache;
	struct rtnl_tc_ops *ops;
	struct nlattr *tb[TCA_MAX + 1];
	char kind[TCKINDSIZ];
	struct tcmsg *tm;
	int err;

	tc->ce_msgtype = n->nlmsg_type;

	err = nlmsg_parse(n, sizeof(*tm), tb, TCA_MAX, tc_policy);
	if (err < 0)
		return err;

	if (tb[TCA_KIND] == NULL)
		return -NLE_MISSING_ATTR;

	nla_strlcpy(kind, tb[TCA_KIND], sizeof(kind));
	rtnl_tc_set_kind(tc, kind);

	tm = nlmsg_data(n);
	tc->tc_family  = tm->tcm_family;
	tc->tc_ifindex = tm->tcm_ifindex;
	tc->tc_handle  = tm->tcm_handle;
	tc->tc_parent  = tm->tcm_parent;
	tc->tc_info    = tm->tcm_info;

	tc->ce_mask |= (TCA_ATTR_FAMILY | TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE|
		        TCA_ATTR_PARENT | TCA_ATTR_INFO);

	if (tb[TCA_OPTIONS]) {
		tc->tc_opts = nl_data_alloc_attr(tb[TCA_OPTIONS]);
		if (!tc->tc_opts)
			return -NLE_NOMEM;
		tc->ce_mask |= TCA_ATTR_OPTS;
	}

	if (tb[TCA_STATS2]) {
		struct nlattr *tbs[TCA_STATS_MAX + 1];

		err = nla_parse_nested(tbs, TCA_STATS_MAX, tb[TCA_STATS2],
				       tc_stats2_policy);
		if (err < 0)
			return err;

		if (tbs[TCA_STATS_BASIC]) {
			struct gnet_stats_basic *bs;
			
			bs = nla_data(tbs[TCA_STATS_BASIC]);
			tc->tc_stats[RTNL_TC_BYTES]	= bs->bytes;
			tc->tc_stats[RTNL_TC_PACKETS]	= bs->packets;
		}

		if (tbs[TCA_STATS_RATE_EST]) {
			struct gnet_stats_rate_est *re;

			re = nla_data(tbs[TCA_STATS_RATE_EST]);
			tc->tc_stats[RTNL_TC_RATE_BPS]	= re->bps;
			tc->tc_stats[RTNL_TC_RATE_PPS]	= re->pps;
		}
		
		if (tbs[TCA_STATS_QUEUE]) {
			struct gnet_stats_queue *q;

			q = nla_data(tbs[TCA_STATS_QUEUE]);
			tc->tc_stats[RTNL_TC_QLEN]	= q->qlen;
			tc->tc_stats[RTNL_TC_BACKLOG]	= q->backlog;
			tc->tc_stats[RTNL_TC_DROPS]	= q->drops;
			tc->tc_stats[RTNL_TC_REQUEUES]	= q->requeues;
			tc->tc_stats[RTNL_TC_OVERLIMITS]	= q->overlimits;
		}

		tc->ce_mask |= TCA_ATTR_STATS;
		
		if (tbs[TCA_STATS_APP]) {
			tc->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]);
			if (tc->tc_xstats == NULL)
				return -NLE_NOMEM;
			tc->ce_mask |= TCA_ATTR_XSTATS;
		} else
			goto compat_xstats;
	} else {
		if (tb[TCA_STATS]) {
			struct tc_stats *st = nla_data(tb[TCA_STATS]);

			tc->tc_stats[RTNL_TC_BYTES]	= st->bytes;
			tc->tc_stats[RTNL_TC_PACKETS]	= st->packets;
			tc->tc_stats[RTNL_TC_RATE_BPS]	= st->bps;
			tc->tc_stats[RTNL_TC_RATE_PPS]	= st->pps;
			tc->tc_stats[RTNL_TC_QLEN]	= st->qlen;
			tc->tc_stats[RTNL_TC_BACKLOG]	= st->backlog;
			tc->tc_stats[RTNL_TC_DROPS]	= st->drops;
			tc->tc_stats[RTNL_TC_OVERLIMITS]= st->overlimits;

			tc->ce_mask |= TCA_ATTR_STATS;
		}

compat_xstats:
		if (tb[TCA_XSTATS]) {
			tc->tc_xstats = nl_data_alloc_attr(tb[TCA_XSTATS]);
			if (tc->tc_xstats == NULL)
				return -NLE_NOMEM;
			tc->ce_mask |= TCA_ATTR_XSTATS;
		}
	}

	ops = rtnl_tc_get_ops(tc);
	if (ops && ops->to_msg_parser) {
		void *data = rtnl_tc_data(tc);

		if (!data)
			return -NLE_NOMEM;

		err = ops->to_msg_parser(tc, data);
		if (err < 0)
			return err;
	}

	if ((link_cache = __nl_cache_mngt_require("route/link"))) {
		struct rtnl_link *link;

		if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) {
			rtnl_tc_set_link(tc, link);

			/* rtnl_tc_set_link incs refcnt */
			rtnl_link_put(link);
		}
	}

	return 0;
}
Ejemplo n.º 4
0
static int u32_msg_parser(struct rtnl_tc *tc, void *data)
{
	struct rtnl_u32 *u = data;
	struct nlattr *tb[TCA_U32_MAX + 1];
	int err;

	err = tca_parse(tb, TCA_U32_MAX, tc, u32_policy);
	if (err < 0)
		return err;

	if (tb[TCA_U32_DIVISOR]) {
		u->cu_divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
		u->cu_mask |= U32_ATTR_DIVISOR;
	}

	if (tb[TCA_U32_SEL]) {
		u->cu_selector = nl_data_alloc_attr(tb[TCA_U32_SEL]);
		if (!u->cu_selector)
			goto errout_nomem;
		u->cu_mask |= U32_ATTR_SELECTOR;
	}

	if (tb[TCA_U32_MARK]) {
		u->cu_mark = nl_data_alloc_attr(tb[TCA_U32_MARK]);
		if (!u->cu_mark)
			goto errout_nomem;
		u->cu_mask |= U32_ATTR_MARK;
	}

	if (tb[TCA_U32_HASH]) {
		u->cu_hash = nla_get_u32(tb[TCA_U32_HASH]);
		u->cu_mask |= U32_ATTR_HASH;
	}

	if (tb[TCA_U32_CLASSID]) {
		u->cu_classid = nla_get_u32(tb[TCA_U32_CLASSID]);
		u->cu_mask |= U32_ATTR_CLASSID;
	}

	if (tb[TCA_U32_LINK]) {
		u->cu_link = nla_get_u32(tb[TCA_U32_LINK]);
		u->cu_mask |= U32_ATTR_LINK;
	}

	if (tb[TCA_U32_ACT]) {
		u->cu_mask |= U32_ATTR_ACTION;
		err = rtnl_act_parse(&u->cu_act, tb[TCA_U32_ACT]);
		if (err)
			return err;
	}

	if (tb[TCA_U32_POLICE]) {
		u->cu_police = nl_data_alloc_attr(tb[TCA_U32_POLICE]);
		if (!u->cu_police)
			goto errout_nomem;
		u->cu_mask |= U32_ATTR_POLICE;
	}

	if (tb[TCA_U32_PCNT]) {
		struct tc_u32_sel *sel;
		size_t pcnt_size;

		if (!tb[TCA_U32_SEL]) {
			err = -NLE_MISSING_ATTR;
			goto errout;
		}

		sel = u->cu_selector->d_data;
		pcnt_size = sizeof(struct tc_u32_pcnt) +
				(sel->nkeys * sizeof(uint64_t));
		if (nla_len(tb[TCA_U32_PCNT]) < pcnt_size) {
			err = -NLE_INVAL;
			goto errout;
		}

		u->cu_pcnt = nl_data_alloc_attr(tb[TCA_U32_PCNT]);
		if (!u->cu_pcnt)
			goto errout_nomem;
		u->cu_mask |= U32_ATTR_PCNT;
	}

	if (tb[TCA_U32_INDEV]) {
		nla_strlcpy(u->cu_indev, tb[TCA_U32_INDEV], IFNAMSIZ);
		u->cu_mask |= U32_ATTR_INDEV;
	}

	return 0;

errout_nomem:
	err = -NLE_NOMEM;
errout:
	return err;
}