/* net device transmit always called with no BH (preempt_disabled) */ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); const unsigned char *dest = skb->data; struct net_bridge_fdb_entry *dst; struct net_bridge_mdb_entry *mdst; BR_INPUT_SKB_CB(skb)->brdev = dev; dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; skb_reset_mac_header(skb); skb_pull(skb, ETH_HLEN); if (dest[0] & 1) { if (br_multicast_rcv(br, NULL, skb)) goto out; mdst = br_mdb_get(br, skb); if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) br_multicast_deliver(mdst, skb); else br_flood_deliver(br, skb); } else if ((dst = __br_fdb_get(br, dest)) != NULL) br_deliver(dst->dst, skb); else br_flood_deliver(br, skb); out: return NETDEV_TX_OK; }
/* net device transmit always called with no BH (preempt_disabled) */ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); const unsigned char *dest = skb->data; struct net_bridge_fdb_entry *dst; #if defined (CONFIG_RTL_IGMP_SNOOPING) struct iphdr *iph=NULL; unsigned char proto=0; unsigned char reserved=0; #if defined (CONFIG_RTL_MLD_SNOOPING) struct ipv6hdr *ipv6h=NULL; #endif struct rtl_multicastDataInfo multicastDataInfo; struct rtl_multicastFwdInfo multicastFwdInfo; int ret=FAILED; #if defined (CONFIG_RTL_HARDWARE_MULTICAST) unsigned int srcPort=skb->srcPort; unsigned int srcVlanId=skb->srcVlanId; #endif #endif dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; skb_reset_mac_header(skb); skb_pull(skb, ETH_HLEN); if (dest[0] & 1) { #if defined (CONFIG_RTL_IGMP_SNOOPING) if(igmpsnoopenabled) { if(MULTICAST_MAC(dest)) { iph=(struct iphdr *)skb_network_header(skb); proto = iph->protocol; #if 0 if(( iph->daddr&0xFFFFFF00)==0xE0000000) { reserved=1; } #endif if( iph->daddr == 0xEFFFFFFA) { /*for microsoft upnp*/ reserved=1; } if(((proto ==IPPROTO_UDP) ||(proto ==IPPROTO_TCP)) && (reserved ==0)) { multicastDataInfo.ipVersion=4; multicastDataInfo.sourceIp[0]= (uint32)(iph->saddr); multicastDataInfo.groupAddr[0]= (uint32)(iph->daddr); ret= rtl_getMulticastDataFwdInfo(brIgmpModuleIndex, &multicastDataInfo, &multicastFwdInfo); if(ret==SUCCESS) { br_multicast_deliver(br, multicastFwdInfo.fwdPortMask, skb, 0); #if defined (CONFIG_RTL_HARDWARE_MULTICAST) if((srcVlanId!=0) && (srcPort!=0xFFFF)) { #if defined(CONFIG_RTK_VLAN_SUPPORT) if(rtk_vlan_support_enable == 0) { rtl865x_ipMulticastHardwareAccelerate(br, multicastFwdInfo.fwdPortMask,srcPort,srcVlanId, multicastDataInfo.sourceIp[0], multicastDataInfo.groupAddr[0]); } #else rtl865x_ipMulticastHardwareAccelerate(br, multicastFwdInfo.fwdPortMask,srcPort,srcVlanId, multicastDataInfo.sourceIp[0], multicastDataInfo.groupAddr[0]); #endif } #endif } else { br_flood_deliver(br, skb); } } else { br_flood_deliver(br, skb); } } #if defined(CONFIG_RTL_MLD_SNOOPING) else if(mldSnoopEnabled && IPV6_MULTICAST_MAC(dest)) { ipv6h=(struct ipv6hdr *)skb_network_header(skb); proto=re865x_getIpv6TransportProtocol(ipv6h); if ((proto ==IPPROTO_UDP) ||(proto ==IPPROTO_TCP)) { multicastDataInfo.ipVersion=6; memcpy(&multicastDataInfo.sourceIp, &ipv6h->saddr, sizeof(struct in6_addr)); memcpy(&multicastDataInfo.groupAddr, &ipv6h->daddr, sizeof(struct in6_addr)); ret= rtl_getMulticastDataFwdInfo(brIgmpModuleIndex, &multicastDataInfo, &multicastFwdInfo); if(ret==SUCCESS) { br_multicast_deliver(br, multicastFwdInfo.fwdPortMask, skb, 0); } else { br_flood_deliver(br, skb); } } else { br_flood_deliver(br, skb); } } #endif else { br_flood_deliver(br, skb); } } else { br_flood_deliver(br, skb); } #else br_flood_deliver(br, skb); #endif } else if ((dst = __br_fdb_get(br, dest)) != NULL) br_deliver(dst->dst, skb); else br_flood_deliver(br, skb); return 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; }