示例#1
0
static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
{
	struct clip_vcc *clip_vcc = CLIP_VCC(vcc);

	pr_debug("\n");

	if (!clip_devs) {
		atm_return(vcc, skb->truesize);
		kfree_skb(skb);
		return;
	}

	if (!skb) {
		pr_debug("removing VCC %p\n", clip_vcc);
		if (clip_vcc->entry)
			unlink_clip_vcc(clip_vcc);
		clip_vcc->old_push(vcc, NULL);	/* pass on the bad news */
		kfree(clip_vcc);
		return;
	}
	atm_return(vcc, skb->truesize);
	skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
	/* clip_vcc->entry == NULL if we don't have an IP address yet */
	if (!skb->dev) {
		dev_kfree_skb_any(skb);
		return;
	}
	ATM_SKB(skb)->vcc = vcc;
	skb_reset_mac_header(skb);
	if (!clip_vcc->encap ||
	    skb->len < RFC1483LLC_LEN ||
	    memcmp(skb->data, llc_oui, sizeof(llc_oui)))
		skb->protocol = htons(ETH_P_IP);
	else {
		skb->protocol = ((__be16 *)skb->data)[3];
		skb_pull(skb, RFC1483LLC_LEN);
		if (skb->protocol == htons(ETH_P_ARP)) {
			skb->dev->stats.rx_packets++;
			skb->dev->stats.rx_bytes += skb->len;
			clip_arp_rcv(skb);
			return;
		}
	}
	clip_vcc->last_use = jiffies;
	skb->dev->stats.rx_packets++;
	skb->dev->stats.rx_bytes += skb->len;
	memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
	netif_rx(skb);
}
示例#2
0
static void svc_disconnect(struct atm_vcc *vcc)
{
	DEFINE_WAIT(wait);
	struct sk_buff *skb;
	struct sock *sk = sk_atm(vcc);

	DPRINTK("svc_disconnect %p\n",vcc);
	if (test_bit(ATM_VF_REGIS,&vcc->flags)) {
		prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
		sigd_enq(vcc,as_close,NULL,NULL,NULL);
		while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) {
			schedule();
			prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
		}
		finish_wait(sk->sk_sleep, &wait);
	}
	/* beware - socket is still in use by atmsigd until the last
	   as_indicate has been answered */
	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
		atm_return(vcc, skb->truesize);
		DPRINTK("LISTEN REL\n");
		sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
		dev_kfree_skb(skb);
	}
	clear_bit(ATM_VF_REGIS, &vcc->flags);
	/* ... may retry later */
}
示例#3
0
static void mpoad_close(struct atm_vcc *vcc)
{
	struct mpoa_client *mpc;
	struct sk_buff *skb;

	mpc = find_mpc_by_vcc(vcc);
	if (mpc == NULL) {
		pr_info("did not find MPC\n");
		return;
	}
	if (!mpc->mpoad_vcc) {
		pr_info("close for non-present mpoad\n");
		return;
	}

	mpc->mpoad_vcc = NULL;
	if (mpc->dev) {
		struct lec_priv *priv = netdev_priv(mpc->dev);
		priv->lane2_ops->associate_indicator = NULL;
		stop_mpc(mpc);
		dev_put(mpc->dev);
	}

	mpc->in_ops->destroy_cache(mpc);
	mpc->eg_ops->destroy_cache(mpc);

	while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) {
		atm_return(vcc, skb->truesize);
		kfree_skb(skb);
	}

	pr_info("(%s) going down\n",
		(mpc->dev) ? mpc->dev->name : "<unknown>");
	module_put(THIS_MODULE);
}
示例#4
0
static void svc_disconnect(struct atm_vcc *vcc)
{
	DEFINE_WAIT(wait);
	struct sk_buff *skb;
	struct sock *sk = sk_atm(vcc);

	pr_debug("svc_disconnect %p\n",vcc);
	if (test_bit(ATM_VF_REGIS,&vcc->flags)) {
		prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
		sigd_enq(vcc,as_close,NULL,NULL,NULL);
		while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) {
			schedule();
			prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
		}
		finish_wait(sk->sk_sleep, &wait);
	}
	
	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
		atm_return(vcc, skb->truesize);
		pr_debug("LISTEN REL\n");
		sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
		dev_kfree_skb(skb);
	}
	clear_bit(ATM_VF_REGIS, &vcc->flags);
	
}
示例#5
0
int atm_charge(struct atm_vcc *vcc,int truesize)
{
	atm_force_charge(vcc,truesize);
	if (atomic_read(&vcc->sk->rmem_alloc) <= vcc->sk->rcvbuf) return 1;
	atm_return(vcc,truesize);
	atomic_inc(&vcc->stats->rx_drop);
	return 0;
}
示例#6
0
int atm_charge(struct atm_vcc *vcc, int truesize)
{
    atm_force_charge(vcc, truesize);
    if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf)
        return 1;
    atm_return(vcc, truesize);
    atomic_inc_unchecked(&vcc->stats->rx_drop);
    return 0;
}
/* Called when an AAL5 PDU comes in */
static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
{
	struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
	pr_debug("\n");
	if (skb == NULL) {			/* VCC was closed */
		pr_debug("removing ATMPPP VCC %p\n", pvcc);
		pppoatm_unassign_vcc(atmvcc);
		atmvcc->push(atmvcc, NULL);	/* Pass along bad news */
		return;
	}
	atm_return(atmvcc, skb->truesize);
	switch (pvcc->encaps) {
	case e_llc:
		if (skb->len < LLC_LEN ||
		    memcmp(skb->data, pppllc, LLC_LEN))
			goto error;
		skb_pull(skb, LLC_LEN);
		break;
	case e_autodetect:
		if (pvcc->chan.ppp == NULL) {	/* Not bound yet! */
			kfree_skb(skb);
			return;
		}
		if (skb->len >= sizeof(pppllc) &&
		    !memcmp(skb->data, pppllc, sizeof(pppllc))) {
			pvcc->encaps = e_llc;
			skb_pull(skb, LLC_LEN);
			break;
		}
		if (skb->len >= (sizeof(pppllc) - LLC_LEN) &&
		    !memcmp(skb->data, &pppllc[LLC_LEN],
		    sizeof(pppllc) - LLC_LEN)) {
			pvcc->encaps = e_vc;
			pvcc->chan.mtu += LLC_LEN;
			break;
		}
		pr_debug("Couldn't autodetect yet (skb: %02X %02X %02X %02X %02X %02X)\n",
			 skb->data[0], skb->data[1], skb->data[2],
			 skb->data[3], skb->data[4], skb->data[5]);
		goto error;
	case e_vc:
		break;
	}
	ppp_input(&pvcc->chan, skb);
	return;

error:
	kfree_skb(skb);
	ppp_input_error(&pvcc->chan, 0);
}
示例#8
0
static int clip_mkip(struct atm_vcc *vcc,int timeout)
{
    struct clip_vcc *clip_vcc;
    struct sk_buff_head copy;
    struct sk_buff *skb;

    if (!vcc->push) return -EBADFD;
    clip_vcc = kmalloc(sizeof(struct clip_vcc),GFP_KERNEL);
    if (!clip_vcc) return -ENOMEM;
    DPRINTK("mkip clip_vcc %p vcc %p\n",clip_vcc,vcc);
    clip_vcc->vcc = vcc;
    vcc->user_back = clip_vcc;
    clip_vcc->entry = NULL;
    clip_vcc->xoff = 0;
    clip_vcc->encap = 1;
    clip_vcc->last_use = jiffies;
    clip_vcc->idle_timeout = timeout*HZ;
    clip_vcc->old_push = vcc->push;
    clip_vcc->old_pop = vcc->pop;
    clip_vcc->dev = NULL;
    clip_vcc->global_next = NULL;
    memset(&clip_vcc->resolve_timer, 0, sizeof(clip_vcc->resolve_timer));
    vcc->push = clip_push;
    vcc->pop = clip_pop;
    skb_queue_head_init(&copy);
    skb_migrate(&vcc->recvq,&copy);
    /* re-process everything received between connection setup and MKIP */
    while ((skb = skb_dequeue(&copy)))
    {
	if (!clip_devs)
	{
	    atm_return(vcc,skb->truesize);
	    kfree_skb(skb);
	}
	else
	{
	    unsigned int len = skb->len;

	    clip_push(vcc,skb);
	    PRIV(skb->dev)->stats.rx_packets--;
	    PRIV(skb->dev)->stats.rx_bytes -= len;
	}
    }
    return 0;
}
示例#9
0
struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
    int gfp_flags)
{
	int guess = atm_guess_pdu2truesize(pdu_size);

	atm_force_charge(vcc,guess);
	if (atomic_read(&vcc->sk->rmem_alloc) <= vcc->sk->rcvbuf) {
		struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags);

		if (skb) {
			atomic_add(skb->truesize-guess,&vcc->sk->rmem_alloc);
			return skb;
		}
	}
	atm_return(vcc,guess);
	atomic_inc(&vcc->stats->rx_drop);
	return NULL;
}
void clip6_push(struct atm_vcc *vcc,struct sk_buff *skb)
{
	struct clip6_vcc *clip6_vcc = CLIP6_VCC(vcc);

	DPRINTK("clip6 push\n");
	if (!skb) {
		DPRINTK("removing VCC %p\n",clip6_vcc);
		clip6_vcc->old_push(vcc,NULL); /* pass on the bad news */
		kfree(clip6_vcc);
		return;
	}
	atm_return(vcc,skb->truesize);
	skb->dev = clip6_vcc->dev;
		/* clip6_vcc->entry == NULL if we don't have an IP address yet */
	if (!skb->dev) {
		dev_kfree_skb_any(skb);
		return;
	}
	ATM_SKB(skb)->vcc = vcc;
	skb->mac.raw = skb->data;
	if (!clip6_vcc->encap || skb->len < RFC1483LLC_LEN || memcmp(skb->data,
	    llc_oui,sizeof(llc_oui))) {
		skb->protocol = ((u16 *) skb->data)[3];
				/* ??? Should I validate skb->protocol is
				   either ETH_P_IPV6 or ETH_P_IP? */
	}
	else {
		skb->protocol = ((u16 *) skb->data)[3];
		skb_pull(skb,RFC1483LLC_LEN);
				/* TODO: check */
#if 0
		if (skb->protocol == htons(ETH_P_ARP)) {
			PRIV(skb->dev)->stats.rx_packets++;
			PRIV(skb->dev)->stats.rx_bytes += skb->len;
			clip6_arp_rcv(skb);
			return;
		}
#endif /* if 0 */
	}
	clip6_vcc->last_use = jiffies;
	PRIV(skb->dev)->stats.rx_packets++;
	PRIV(skb->dev)->stats.rx_bytes += skb->len;
	netif_rx(skb);
}
示例#11
0
文件: atm_misc.c 项目: 020gzh/linux
struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc, int pdu_size,
				 gfp_t gfp_flags)
{
	struct sock *sk = sk_atm(vcc);
	int guess = SKB_TRUESIZE(pdu_size);

	atm_force_charge(vcc, guess);
	if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
		struct sk_buff *skb = alloc_skb(pdu_size, gfp_flags);

		if (skb) {
			atomic_add(skb->truesize-guess,
				   &sk->sk_rmem_alloc);
			return skb;
		}
	}
	atm_return(vcc, guess);
	atomic_inc(&vcc->stats->rx_drop);
	return NULL;
}
示例#12
0
void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
{
    struct clip_vcc *clip_vcc = CLIP_VCC(vcc);

    DPRINTK("clip push\n");
    if (!skb)
    {
	clip_vcc_remove(clip_vcc);
	return;
    }
    atm_return(vcc, skb->truesize);
    skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
    /* clip_vcc->entry == NULL if we don't have an IP address yet */
    if (!skb->dev)
    {
	dev_kfree_skb_any(skb);
	return;
    }
    ATM_SKB(skb)->vcc = vcc;
    skb->mac.raw = skb->data;
    if (!clip_vcc->encap || skb->len < RFC1483LLC_LEN || memcmp(skb->data,
	llc_oui, sizeof(llc_oui))) skb->protocol = htons(ETH_P_IP);
    else
    {
	skb->protocol = ((u16 *) skb->data)[3];
	skb_pull(skb, RFC1483LLC_LEN);
	if (skb->protocol == htons(ETH_P_ARP))
	{
	    PRIV(skb->dev)->stats.rx_packets++;
	    PRIV(skb->dev)->stats.rx_bytes += skb->len;
	    clip_arp_rcv(skb);
	    return;
	}
    }
    clip_vcc->last_use = jiffies;
    PRIV(skb->dev)->stats.rx_packets++;
    PRIV(skb->dev)->stats.rx_bytes += skb->len;
    netif_rx(skb);
}
示例#13
0
static void vcc_destroy_socket(struct sock *sk)
{
	struct atm_vcc *vcc = atm_sk(sk);
	struct sk_buff *skb;

	clear_bit(ATM_VF_READY, &vcc->flags);
	if (vcc->dev) {
		if (vcc->dev->ops->close)
			vcc->dev->ops->close(vcc);
		if (vcc->push)
			vcc->push(vcc, NULL); /* atmarpd has no push */

		vcc_remove_socket(sk);	/* no more receive */

		while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue)) != NULL) {
			atm_return(vcc,skb->truesize);
			kfree_skb(skb);
		}

		module_put(vcc->dev->ops->owner);
		atm_dev_put(vcc->dev);
	}
}
示例#14
0
static void mpoad_close(struct atm_vcc *vcc)
{
	struct mpoa_client *mpc;
	struct sk_buff *skb;

	mpc = find_mpc_by_vcc(vcc);
	if (mpc == NULL) {
		printk("mpoa: mpoad_close: did not find MPC\n");
		return;
	}
	if (!mpc->mpoad_vcc) {
		printk("mpoa: mpoad_close: close for non-present mpoad\n");
		return;
	}
	
	mpc->mpoad_vcc = NULL;
	if (mpc->dev) {
		struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
		priv->lane2_ops->associate_indicator = NULL;
		stop_mpc(mpc);
		dev_put(mpc->dev);
	}

	mpc->in_ops->destroy_cache(mpc);
	mpc->eg_ops->destroy_cache(mpc);

	while ( (skb = skb_dequeue(&vcc->sk->receive_queue)) ){
		atm_return(vcc, skb->truesize);
		kfree_skb(skb);
	}
	
	printk("mpoa: (%s) going down\n",
		(mpc->dev) ? mpc->dev->name : "<unknown>");
	MOD_DEC_USE_COUNT;

	return;
}
示例#15
0
static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
{
	struct net_device *dev = (struct net_device *)vcc->proto_data;
	struct sk_buff *new_skb;
	eg_cache_entry *eg;
	struct mpoa_client *mpc;
	uint32_t tag;
	char *tmp;
	
	ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
	if (skb == NULL) {
		dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name);
		mpc_vcc_close(vcc, dev);
		return;
	}
	
	skb->dev = dev;
	if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
		struct sock *sk = sk_atm(vcc);

		dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
		/* Pass control packets to daemon */
		skb_queue_tail(&sk->sk_receive_queue, skb);
		sk->sk_data_ready(sk, skb->len);
		return;
	}

	/* data coming over the shortcut */
	atm_return(vcc, skb->truesize);

	mpc = find_mpc_by_lec(dev);
	if (mpc == NULL) {
		printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name);
		return;
	}

	if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
		ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name);

	} else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
		printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name);
		printk("           mpc_push: non-tagged data unsupported, purging\n");
		dev_kfree_skb_any(skb);
		return;
	} else {
		printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name);
		dev_kfree_skb_any(skb);
		return;
	}

	tmp = skb->data + sizeof(struct llc_snap_hdr);
	tag = *(uint32_t *)tmp;

	eg = mpc->eg_ops->get_by_tag(tag, mpc);
	if (eg == NULL) {
		printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n",
		       dev->name,tag);
		purge_egress_shortcut(vcc, NULL);
		dev_kfree_skb_any(skb);
		return;
	}
	
	/*
	 * See if ingress MPC is using shortcut we opened as a return channel.
	 * This means we have a bi-directional vcc opened by us.
	 */ 
	if (eg->shortcut == NULL) {
		eg->shortcut = vcc;
		printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name);
	}

	skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */
	new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */
	dev_kfree_skb_any(skb);
	if (new_skb == NULL){
		mpc->eg_ops->put(eg);
		return;
	}
	skb_push(new_skb, eg->ctrl_info.DH_length);     /* add MAC header */
	memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length);
	new_skb->protocol = eth_type_trans(new_skb, dev);
	new_skb->nh.raw = new_skb->data;

	eg->latest_ip_addr = new_skb->nh.iph->saddr;
	eg->packets_rcvd++;
	mpc->eg_ops->put(eg);

	memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
	netif_rx(new_skb);

	return;
}
示例#16
0
static int clip_mkip(struct atm_vcc *vcc, int timeout)
{
	struct clip_vcc *clip_vcc;
	struct sk_buff *skb;
	struct sk_buff_head *rq;
	unsigned long flags;

	if (!vcc->push)
		return -EBADFD;
	clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL);
	if (!clip_vcc)
		return -ENOMEM;
	DPRINTK("mkip clip_vcc %p vcc %p\n", clip_vcc, vcc);
	clip_vcc->vcc = vcc;
	vcc->user_back = clip_vcc;
	set_bit(ATM_VF_IS_CLIP, &vcc->flags);
	clip_vcc->entry = NULL;
	clip_vcc->xoff = 0;
	clip_vcc->encap = 1;
	clip_vcc->last_use = jiffies;
	clip_vcc->idle_timeout = timeout * HZ;
	clip_vcc->old_push = vcc->push;
	clip_vcc->old_pop = vcc->pop;
	vcc->push = clip_push;
	vcc->pop = clip_pop;

	rq = &sk_atm(vcc)->sk_receive_queue;

	spin_lock_irqsave(&rq->lock, flags);
	if (skb_queue_empty(rq)) {
		skb = NULL;
	} else {
		/* NULL terminate the list.  */
		rq->prev->next = NULL;
		skb = rq->next;
	}
	rq->prev = rq->next = (struct sk_buff *)rq;
	rq->qlen = 0;
	spin_unlock_irqrestore(&rq->lock, flags);

	/* re-process everything received between connection setup and MKIP */
	while (skb) {
		struct sk_buff *next = skb->next;

		skb->next = skb->prev = NULL;
		if (!clip_devs) {
			atm_return(vcc, skb->truesize);
			kfree_skb(skb);
		} else {
			unsigned int len = skb->len;

			skb_get(skb);
			clip_push(vcc, skb);
			PRIV(skb->dev)->stats.rx_packets--;
			PRIV(skb->dev)->stats.rx_bytes -= len;
			kfree_skb(skb);
		}

		skb = next;
	}
	return 0;
}