Esempio n. 1
0
static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct net_bridge *br;
	unsigned char *dest;
	struct net_bridge_fdb_entry *dst;

	br = dev->priv;
	br->statistics.tx_packets++;
	br->statistics.tx_bytes += skb->len;

	dest = skb->mac.raw = skb->data;
	skb_pull(skb, ETH_HLEN);

	if (dest[0] & 1) {
		br_flood_deliver(br, skb, 0);
		return 0;
	}

	if ((dst = br_fdb_get(br, dest)) != NULL) {
		br_deliver(dst->dst, skb);
		br_fdb_put(dst);
		return 0;
	}

	br_flood_deliver(br, skb, 0);
	return 0;
}
Esempio n. 2
0
void br_fdb_cleanup(struct net_bridge *br)
{
	int i;
	unsigned long timeout;

	timeout = __timeout(br);

	write_lock_bh(&br->hash_lock);
	for (i=0;i<BR_HASH_SIZE;i++) {
		struct net_bridge_fdb_entry *f;

		f = br->hash[i];
		while (f != NULL) {
			struct net_bridge_fdb_entry *g;

			g = f->next_hash;
			if (!f->is_static &&
			    time_before_eq(f->ageing_timer, timeout)) {
				__hash_unlink(f);
				br_fdb_put(f);
			}
			f = g;
		}
	}
	write_unlock_bh(&br->hash_lock);
}
Esempio n. 3
0
void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
{
	int i;

	write_lock_bh(&br->hash_lock);
	for (i=0;i<BR_HASH_SIZE;i++) {
		struct net_bridge_fdb_entry *f;

		f = br->hash[i];
		while (f != NULL) {
			struct net_bridge_fdb_entry *g;

			g = f->next_hash;
			if (f->dst == p) {
				__hash_unlink(f);
				br_fdb_put(f);
			}
			f = g;
		}
	}
	write_unlock_bh(&br->hash_lock);
}
static int br_handle_frame_finish(struct sk_buff *skb)
{
	struct net_bridge *br;
	unsigned char *dest;
	struct net_bridge_fdb_entry *dst;
	struct net_bridge_port *p;
	int passedup;

	dest = skb->mac.ethernet->h_dest;

	p = skb->dev->br_port;
	if (p == NULL)
		goto err_nolock;

	br = p->br;
	read_lock(&br->lock);
	if (skb->dev->br_port == NULL)
		goto err;

	passedup = 0;
	if (br->dev.flags & IFF_PROMISC) {
		struct sk_buff *skb2;

		skb2 = skb_clone(skb, GFP_ATOMIC);
		if (skb2 != NULL) {
			passedup = 1;
			br_pass_frame_up(br, skb2);
		}
	}

	if (dest[0] & 1) {
		br_flood_forward(br, skb, !passedup);
		if (!passedup)
			br_pass_frame_up(br, skb);
		goto out;
	}

	dst = br_fdb_get(br, dest);
	if (dst != NULL && dst->is_local) {
		if (!passedup)
			br_pass_frame_up(br, skb);
		else
			kfree_skb(skb);
		br_fdb_put(dst);
		goto out;
	}

	if (dst != NULL) {
		br_forward(dst->dst, skb);
		br_fdb_put(dst);
		goto out;
	}

	br_flood_forward(br, skb, 0);

out:
	read_unlock(&br->lock);
	return 0;

err:
	read_unlock(&br->lock);
err_nolock:
	kfree_skb(skb);
	return 0;
}
Esempio n. 5
0
static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct net_bridge *br;
	unsigned char *dest;
	struct net_bridge_fdb_entry *dst;
#ifdef IGMP_SNOOPING
	struct iphdr *iph;
	unsigned int ipaddr=0;
	unsigned char proto=0;
	//unsigned char reserved=0;
	extern int igmpsnoopenabled;

	iph = skb->nh.iph;
	ipaddr = iph->daddr;
	proto = iph->protocol;
	//Brad disable 20080619	
	//	if ((ipaddr&0xF0FFFF00) == 0xE0000000)
	//		reserved=1;
		
#endif

	br = dev->priv;
	br->statistics.tx_packets++;
	br->statistics.tx_bytes += skb->len;

	dest = skb->mac.raw = skb->data;
	skb_pull(skb, ETH_HLEN);

	if (dest[0] & 1) {
#ifdef IGMP_SNOOPING
		if(igmpsnoopenabled && 
			(MULTICAST_MAC(dest) || IPV6_MULTICAST_MAC(dest))&& 
			(proto != IPPROTO_IGMP) && (ipaddr != 0xEFFFFFFA) 
			//&& (reserved == 0)
			) {
			if ((dst = br_fdb_get(br, dest)) != NULL) {
				br_multicast_deliver(br, dst, skb, 0);
				br_fdb_put(dst);
			}
			else {
				br_flood_deliver(br, skb, 0);
			}
		}
		else { // broadcast
			br_flood_deliver(br, skb, 0);
		}
		return 0;
#else
		br_flood_deliver(br, skb, 0);
		return 0;
#endif
	}

	if ((dst = br_fdb_get(br, dest)) != NULL) {
#ifdef NAT_SPEEDUP
		if (skb->dst && skb->dst->hh && skb->dst->hh->fdb_cache==NULL) {
			skb->dst->hh->fdb_cache = (void*)dst;
			dst->hh_ptr = skb->dst->hh;
		}
#endif
		br_deliver(dst->dst, skb);
		br_fdb_put(dst);
		return 0;
	}

	br_flood_deliver(br, skb, 0);
	return 0;
}
Esempio n. 6
0
int br_fdb_get_entries(struct net_bridge *br,
		       unsigned char *_buf,
		       int maxnum,
		       int offset)
{
	int i;
	int num;
	struct __fdb_entry *walk;

	num = 0;
	walk = (struct __fdb_entry *)_buf;

	read_lock_bh(&br->hash_lock);
	for (i=0;i<BR_HASH_SIZE;i++) {
		struct net_bridge_fdb_entry *f;

		f = br->hash[i];
		while (f != NULL && num < maxnum) {
			struct __fdb_entry ent;
			int err;
			struct net_bridge_fdb_entry *g;
			struct net_bridge_fdb_entry **pp; 

			if (has_expired(br, f)) {
				f = f->next_hash;
				continue;
			}

			if (offset) {
				offset--;
				f = f->next_hash;
				continue;
			}

			copy_fdb(&ent, f);

			atomic_inc(&f->use_count);
			read_unlock_bh(&br->hash_lock);
			err = copy_to_user(walk, &ent, sizeof(struct __fdb_entry));
			read_lock_bh(&br->hash_lock);

			g = f->next_hash;
			pp = f->pprev_hash;
			br_fdb_put(f);

			if (err)
				goto out_fault;

			if (g == NULL && pp == NULL)
				goto out_disappeared;

			num++;
			walk++;

			f = g;
		}
	}

 out:
	read_unlock_bh(&br->hash_lock);
	return num;

 out_disappeared:
	num = -EAGAIN;
	goto out;

 out_fault:
	num = -EFAULT;
	goto out;
}