Exemple #1
0
static struct rtattr *
find_dump_kind(struct nlmsghdr *n)
{
	struct rtattr *tb1, *tb2[TCA_ACT_MAX+1];
	struct rtattr *tb[TCA_ACT_MAX_PRIO + 1];
	struct rtattr *rta[TCAA_MAX + 1];
	struct rtattr *kind;
	int min_len = NLMSG_LENGTH(sizeof(struct tcamsg));
	int attrlen = n->nlmsg_len - NLMSG_ALIGN(min_len);
	struct rtattr *attr = (void *) n + NLMSG_ALIGN(min_len);

	if (rtattr_parse(rta, TCAA_MAX, attr, attrlen) < 0)
		return NULL;
	tb1 = rta[TCA_ACT_TAB - 1];
	if (tb1 == NULL)
		return NULL;

	if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(tb1),
	                 NLMSG_ALIGN(RTA_PAYLOAD(tb1))) < 0)
		return NULL;
	if (tb[0] == NULL)
		return NULL;

	if (rtattr_parse(tb2, TCA_ACT_MAX, RTA_DATA(tb[0]),
	                 RTA_PAYLOAD(tb[0])) < 0)
		return NULL;
	kind = tb2[TCA_ACT_KIND-1];

	return kind;
}
static int netem_change(struct Qdisc *sch, struct rtattr *opt)
{
	struct netem_sched_data *q = qdisc_priv(sch);
	struct tc_netem_qopt *qopt;
	int ret;
	
	if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
		return -EINVAL;

	qopt = RTA_DATA(opt);
	ret = set_fifo_limit(q->qdisc, qopt->limit);
	if (ret) {
		pr_debug("netem: can't set fifo limit\n");
		return ret;
	}
	
	q->latency = qopt->latency;
	q->jitter = qopt->jitter;
	q->limit = qopt->limit;
	q->gap = qopt->gap;
	q->loss = qopt->loss;
	q->duplicate = qopt->duplicate;

	/* Handle nested options after initial queue options.
	 * Should have put all options in nested format but too late now.
	 */ 
	if (RTA_PAYLOAD(opt) > sizeof(*qopt)) {
		struct rtattr *tb[TCA_NETEM_MAX];
		if (rtattr_parse(tb, TCA_NETEM_MAX, 
				 RTA_DATA(opt) + sizeof(*qopt),
				 RTA_PAYLOAD(opt) - sizeof(*qopt)))
			return -EINVAL;

		if (tb[TCA_NETEM_CORR-1]) {
			ret = get_correlation(sch, tb[TCA_NETEM_CORR-1]);
			if (ret)
				return ret;
		}

		if (tb[TCA_NETEM_DELAY_DIST-1]) {
			ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST-1]);
			if (ret)
				return ret;
		}
	}


	return 0;
}
Exemple #3
0
static int tbf_init(struct Qdisc* sch, struct rtattr *opt)
{
	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
	struct rtattr *tb[TCA_TBF_PTAB];
	struct tc_tbf_qopt *qopt;

	MOD_INC_USE_COUNT;

	if (opt == NULL ||
	    rtattr_parse(tb, TCA_TBF_PTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
	    tb[TCA_TBF_PARMS-1] == NULL ||
	    RTA_PAYLOAD(tb[TCA_TBF_PARMS-1]) < sizeof(*qopt)) {
		MOD_DEC_USE_COUNT;
		return -EINVAL;
	}

	qopt = RTA_DATA(tb[TCA_TBF_PARMS-1]);
	q->R_tab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB-1]);
	if (q->R_tab == NULL) {
		MOD_DEC_USE_COUNT;
		return -EINVAL;
	}

	if (qopt->peakrate.rate) {
		q->P_tab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_PTAB-1]);
		if (q->P_tab == NULL) {
			MOD_DEC_USE_COUNT;
			qdisc_put_rtab(q->R_tab);
			return -EINVAL;
		}
	}

	PSCHED_GET_TIME(q->t_c);
	init_timer(&q->wd_timer);
	q->wd_timer.function = tbf_watchdog;
	q->wd_timer.data = (unsigned long)sch;
	q->limit = qopt->limit;
	q->mtu = qopt->mtu;
	if (q->mtu == 0)
		q->mtu = psched_mtu(sch->dev);
	q->buffer = qopt->buffer;
	q->tokens = q->buffer;
	q->ptokens = q->mtu;
	return 0;
}
Exemple #4
0
static int
tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, int ovr, int bind)
{
	struct ipt_entry_target *t;
	unsigned h;
	struct rtattr *tb[TCA_IPT_MAX];
	struct tcf_ipt *p;
	int ret = 0;
	u32 index = 0;
	u32 hook = 0;

	if (NULL == a || NULL == rta ||
	    (rtattr_parse(tb, TCA_IPT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) <
	     0)) {
		return -1;
	}


	if (tb[TCA_IPT_INDEX - 1]) {
		index = *(u32 *) RTA_DATA(tb[TCA_IPT_INDEX - 1]);
		DPRINTK("ipt index %d\n", index);
	}

	if (index && (p = tcf_hash_lookup(index)) != NULL) {
		a->priv = (void *) p;
		spin_lock(&p->lock);
		if (bind) {
			p->bindcnt += 1;
			p->refcnt += 1;
		}
		if (ovr) {
			goto override;
		}
		spin_unlock(&p->lock);
		return ret;
	}
struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
{
	unsigned h;
	struct tcf_police *p;
	struct rtattr *tb[TCA_POLICE_MAX];
	struct tc_police *parm;

	if (rtattr_parse(tb, TCA_POLICE_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
		return NULL;

	if (tb[TCA_POLICE_TBF-1] == NULL)
		return NULL;

	parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);

	if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
		p->refcnt++;
		return p;
	}

	p = kmalloc(sizeof(*p), GFP_KERNEL);
	if (p == NULL)
		return NULL;

	memset(p, 0, sizeof(*p));
	p->refcnt = 1;
	spin_lock_init(&p->lock);
	p->stats.lock = &p->lock;
	if (parm->rate.rate) {
		if ((p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1])) == NULL)
			goto failure;
		if (parm->peakrate.rate &&
		    (p->P_tab = qdisc_get_rtab(&parm->peakrate, tb[TCA_POLICE_PEAKRATE-1])) == NULL)
			goto failure;
	}
	if (tb[TCA_POLICE_RESULT-1])
		p->result = *(int*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
#ifdef CONFIG_NET_ESTIMATOR
	if (tb[TCA_POLICE_AVRATE-1])
		p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
#endif
	p->toks = p->burst = parm->burst;
	p->mtu = parm->mtu;
	if (p->mtu == 0) {
		p->mtu = ~0;
		if (p->R_tab)
			p->mtu = 255<<p->R_tab->rate.cell_log;
	}
	if (p->P_tab)
		p->ptoks = L2T_P(p, p->mtu);
	PSCHED_GET_TIME(p->t_c);
	p->index = parm->index ? : tcf_police_new_index();
	p->action = parm->action;
#ifdef CONFIG_NET_ESTIMATOR
	if (est)
		qdisc_new_estimator(&p->stats, est);
#endif
	h = tcf_police_hash(p->index);
	write_lock_bh(&police_lock);
	p->next = tcf_police_ht[h];
	tcf_police_ht[h] = p;
	write_unlock_bh(&police_lock);
	return p;

failure:
	if (p->R_tab)
		qdisc_put_rtab(p->R_tab);
	kfree(p);
	return NULL;
}
Exemple #6
0
static int neigh_update(struct nlmsghdr *nlh)
{
    int err;
    int len = nlh->nlmsg_len;
    uint32_t index;
    char *pifname;
    char if_name[IF_NAMESIZE];
    char buf[512] = {0};
    struct ndmsg *ndm;
    struct rtattr *rta;
    struct rtattr *tb[NDA_MAX+1];
    struct nda_cacheinfo *ci = NULL;
    struct msg_hdr *hdr;
    struct arp_add *arp_add;
    struct arp_del *arp_del;
    struct route_add *rt_add;
    struct route_del *rt_del;

    len -= NLMSG_LENGTH(sizeof(*ndm));
    if (len < 0)
        return -1;
    
    ndm = NLMSG_DATA(nlh);
    hdr = (struct msg_hdr *)buf;

    if (ndm->ndm_type != RTN_UNICAST)
        return 0;

    if (AF_INET != ndm->ndm_family && AF_INET6 != ndm->ndm_family) {
        fastpath_log_debug("family %d error.\n", ndm->ndm_family);
        return 0;
    }

    index = get_port_map(ndm->ndm_ifindex);
    if (index >= ROUTE_MAX_LINK) {
        fastpath_log_debug("ifidx %d not concerned\n", ndm->ndm_ifindex);
        return 0;
    }

    pifname = if_indextoname(ndm->ndm_ifindex, if_name);
    if (pifname == NULL) {
        fastpath_log_error("%s:get if name by ifindex:%d err\n", 
                  __func__, ndm->ndm_ifindex);
        return -EIO;
    }

    rta = (struct rtattr*)((char*)ndm + NLMSG_ALIGN(sizeof(struct ndmsg)));
    
    rtattr_parse(tb, NDA_MAX, rta, len);

    if (NULL == tb[NDA_DST]) {
        fastpath_log_error( "nda dst is null.\n");
        return -EINVAL;
    }
    
    if (NULL != tb[NDA_CACHEINFO]) {
        ci = RTA_DATA(tb[NDA_CACHEINFO]);
    }

    fastpath_log_debug( "%s: neigh update, family %d, ifidx %d, eif%d, state 0x%02x\n",
        __func__, ndm->ndm_family, ndm->ndm_ifindex, index, ndm->ndm_state);

    if (ndm->ndm_state & NUD_FAILED || (ci && (ci->ndm_refcnt == 0))) {
        hdr->cmd = ROUTE_MSG_DEL_NEIGH;
        arp_del = (struct arp_del *)hdr->data;
        arp_del->nh_iface = rte_cpu_to_be_32(index);
        memcpy(&arp_del->nh_ip, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
        err = route_send(hdr);
        if (err != 0) {
            fastpath_log_error( "neigh_update: send neigh failed\n", __func__);
        }

        hdr->cmd = ROUTE_MSG_DEL_NH;
        rt_del = (struct route_del *)hdr->data;
        memcpy(&rt_del->ip, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
        rt_del->depth = 32;
        err = route_send(hdr);
        if (err != 0) {
            fastpath_log_error( "neigh_update: send nh failed\n");
        }
        
    } else /* if (ndm->ndm_state & (NUD_REACHABLE | NUD_PERMANENT)) */ {
        hdr->cmd = ROUTE_MSG_ADD_NEIGH;
        arp_add = (struct arp_add *)hdr->data;
        arp_add->nh_iface = rte_cpu_to_be_32(index);
        memcpy(&arp_add->nh_ip, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
        arp_add->type = rte_cpu_to_be_16(NEIGH_TYPE_REACHABLE);
        if (NULL != tb[NDA_LLADDR]) {
            memcpy(&arp_add->nh_arp, (char*)RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR]));
        }
        err = route_send(hdr);
        if (err != 0) {
            fastpath_log_error( "neigh_update: send neigh failed\n", __func__);
        }

        hdr->cmd = ROUTE_MSG_ADD_NH;
        rt_add = (struct route_add *)hdr->data;
        memcpy(&rt_add->ip, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
        rt_add->depth = 32;
        memcpy(&rt_add->nh_ip, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
        rt_add->nh_iface = rte_cpu_to_be_32(index);
        err = route_send(hdr);
        if (err != 0) {
            fastpath_log_error( "neigh_update: send nh failed\n");
        }
    }
#if 0
    else {
Exemple #7
0
static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
{
    int err = -EINVAL;
    struct tbf_sched_data *q = qdisc_priv(sch);
    struct rtattr *tb[TCA_TBF_PTAB];
    struct tc_tbf_qopt *qopt;
    struct qdisc_rate_table *rtab = NULL;
    struct qdisc_rate_table *ptab = NULL;
    struct Qdisc *child = NULL;
    int max_size,n;

    if (rtattr_parse(tb, TCA_TBF_PTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
            tb[TCA_TBF_PARMS-1] == NULL ||
            RTA_PAYLOAD(tb[TCA_TBF_PARMS-1]) < sizeof(*qopt))
        goto done;

    qopt = RTA_DATA(tb[TCA_TBF_PARMS-1]);
    rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB-1]);
    if (rtab == NULL)
        goto done;

    if (qopt->peakrate.rate) {
        if (qopt->peakrate.rate > qopt->rate.rate)
            ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB-1]);
        if (ptab == NULL)
            goto done;
    }

    for (n = 0; n < 256; n++)
        if (rtab->data[n] > qopt->buffer) break;
    max_size = (n << qopt->rate.cell_log)-1;
    if (ptab) {
        int size;

        for (n = 0; n < 256; n++)
            if (ptab->data[n] > qopt->mtu) break;
        size = (n << qopt->peakrate.cell_log)-1;
        if (size < max_size) max_size = size;
    }
    if (max_size < 0)
        goto done;

    if (q->qdisc == &noop_qdisc) {
        if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL)
            goto done;
    }

    sch_tree_lock(sch);
    if (child) q->qdisc = child;
    q->limit = qopt->limit;
    q->mtu = qopt->mtu;
    q->max_size = max_size;
    q->buffer = qopt->buffer;
    q->tokens = q->buffer;
    q->ptokens = q->mtu;
    rtab = xchg(&q->R_tab, rtab);
    ptab = xchg(&q->P_tab, ptab);
    sch_tree_unlock(sch);
    err = 0;
done:
    if (rtab)
        qdisc_put_rtab(rtab);
    if (ptab)
        qdisc_put_rtab(ptab);
    return err;
}