--- zzzz-none-000/linux-2.6.32.61/net/core/dev.c 2013-06-10 09:43:48.000000000 +0000 +++ ar10-7272-687/linux-2.6.32.61/net/core/dev.c 2015-07-14 09:41:24.000000000 +0000 @@ -96,6 +96,12 @@ #include #include #include +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) +#include +#endif +#ifdef CONFIG_AVM_PA +#include +#endif #include #include #include @@ -130,6 +136,11 @@ #include "net-sysfs.h" +#if defined(CONFIG_LTQ_UDP_REDIRECT) || defined(CONFIG_LTQ_UDP_REDIRECT_MODULE) +#include +#include +#endif + /* Instead of increasing this, you should create a hash table. */ #define MAX_GRO_SKBS 8 @@ -170,6 +181,8 @@ static DEFINE_SPINLOCK(ptype_lock); static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; static struct list_head ptype_all __read_mostly; /* Taps */ +static int (*avm_recvhook)(struct sk_buff *skb); +static int (*avm_early_recvhook)(struct sk_buff *skb); /* * The @dev_base_head list is protected by @dev_base_lock and the rtnl @@ -339,6 +352,18 @@ *******************************************************************************/ +void set_avm_recvhook(int (*recvhook)(struct sk_buff *skb)) +{ + avm_recvhook = recvhook; +} +EXPORT_SYMBOL(set_avm_recvhook); + +void set_avm_early_recvhook(int (*recvhook)(struct sk_buff *skb)) +{ + avm_early_recvhook = recvhook; +} +EXPORT_SYMBOL(set_avm_early_recvhook); + /* * Add a protocol ID to the list. Now that the input handler is * smarter we can dispense with all the messy stuff that used to be @@ -613,7 +638,12 @@ struct net_device *dev_get_by_name(struct net *net, const char *name) { struct net_device *dev; - + +#if defined(CONFIG_IFX_PPA_API) || defined(CONFIG_IFX_PPA_API_MODULE) + if (net == NULL) { + net = &init_net; + } +#endif read_lock(&dev_base_lock); dev = __dev_get_by_name(net, name); if (dev) @@ -967,8 +997,7 @@ */ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) { - char *new_ifalias; - + char *new_ifalias; ASSERT_RTNL(); if (len >= IFALIASZ) @@ -982,10 +1011,10 @@ return 0; } - new_ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); + new_ifalias= krealloc(dev->ifalias, len + 1, GFP_KERNEL); if (!new_ifalias) return -ENOMEM; - dev->ifalias = new_ifalias; + dev->ifalias = new_ifalias; strlcpy(dev->ifalias, alias, len+1); return len; @@ -1039,6 +1068,7 @@ void dev_load(struct net *net, const char *name) { +#ifdef CONFIG_NET_DEV_LOAD struct net_device *dev; int no_module; @@ -1055,6 +1085,7 @@ "with CAP_SYS_MODULE (deprecated). Use CAP_NET_ADMIN and alias netdev-%s " "instead\n", name); } +#endif /*--- #ifdef CONFIG_NET_DEV_LOAD ---*/ } EXPORT_SYMBOL(dev_load); @@ -1341,6 +1372,12 @@ { return raw_notifier_call_chain(&netdev_chain, val, dev); } +/* AVM: not exported in 2.6.32, exported since around 2.6.38 + * + * commit: + * edf947f10074fea27fdb1730524dca59355a1c40 bridge: notify applications if address of bridge device changes + */ +EXPORT_SYMBOL(call_netdevice_notifiers); /* When > 0 there are consumers of rx skb time stamps */ static atomic_t netstamp_needed = ATOMIC_INIT(0); @@ -1716,7 +1753,11 @@ int rc; if (likely(!skb->next)) { - if (!list_empty(&ptype_all)) + if (!list_empty(&ptype_all) +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) + && !(skb->imq_flags & IMQ_F_ENQUEUE) +#endif + ) dev_queue_xmit_nit(skb, dev); if (netif_needs_gso(dev, skb)) { @@ -1809,7 +1850,7 @@ } EXPORT_SYMBOL(skb_tx_hash); -static struct netdev_queue *dev_pick_tx(struct net_device *dev, +struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb) { const struct net_device_ops *ops = dev->netdev_ops; @@ -1823,6 +1864,9 @@ skb_set_queue_mapping(skb, queue_index); return netdev_get_tx_queue(dev, queue_index); } +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) +EXPORT_SYMBOL(dev_pick_tx); +#endif static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, struct net_device *dev, @@ -1890,6 +1934,8 @@ struct Qdisc *q; int rc = -ENOMEM; + skb_track_caller(skb); + /* GSO will handle the following emulations directly. */ if (netif_needs_gso(dev, skb)) goto gso; @@ -1919,6 +1965,11 @@ } gso: + +#ifdef CONFIG_AVM_PA + (void)avm_pa_dev_snoop_transmit(AVM_PA_DEVINFO(dev), skb); +#endif + /* Disable soft irqs for various locks below. Also * stops preemption for RCU. */ @@ -2013,11 +2064,20 @@ * */ +#ifdef CONFIG_LTQ_BR_OPT +int __bridge netif_rx(struct sk_buff *skb) +#else int netif_rx(struct sk_buff *skb) +#endif { struct softnet_data *queue; unsigned long flags; + skb_track_caller(skb); + +#ifdef CONFIG_MAPPING + if (skb->dev != NULL) +#endif /* if netpoll wants it, pretend we never saw it */ if (netpoll_rx(skb)) return NET_RX_DROP; @@ -2036,6 +2096,9 @@ if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { if (queue->input_pkt_queue.qlen) { enqueue: +#ifdef CONFIG_MAPPING + if (skb->dev != NULL) +#endif __skb_queue_tail(&queue->input_pkt_queue, skb); local_irq_restore(flags); return NET_RX_SUCCESS; @@ -2131,66 +2194,14 @@ return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } -#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE) - -#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) +#if (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)) && \ + (defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)) /* This hook is defined here for ATM LANE */ int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr) __read_mostly; EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook); #endif -/* - * If bridge module is loaded call bridging hook. - * returns NULL if packet was consumed. - */ -struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, - struct sk_buff *skb) __read_mostly; -EXPORT_SYMBOL_GPL(br_handle_frame_hook); - -static inline struct sk_buff *handle_bridge(struct sk_buff *skb, - struct packet_type **pt_prev, int *ret, - struct net_device *orig_dev) -{ - struct net_bridge_port *port; - - if (skb->pkt_type == PACKET_LOOPBACK || - (port = rcu_dereference(skb->dev->br_port)) == NULL) - return skb; - - if (*pt_prev) { - *ret = deliver_skb(skb, *pt_prev, orig_dev); - *pt_prev = NULL; - } - - return br_handle_frame_hook(port, skb); -} -#else -#define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) -#endif - -#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE) -struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly; -EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook); - -static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, - struct packet_type **pt_prev, - int *ret, - struct net_device *orig_dev) -{ - if (skb->dev->macvlan_port == NULL) - return skb; - - if (*pt_prev) { - *ret = deliver_skb(skb, *pt_prev, orig_dev); - *pt_prev = NULL; - } - return macvlan_handle_frame_hook(skb); -} -#else -#define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb) -#endif - #ifdef CONFIG_NET_CLS_ACT /* TODO: Maybe we should just force sch_ingress to be compiled in * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions @@ -2287,6 +2298,53 @@ } /** + * netdev_rx_handler_register - register receive handler + * @dev: device to register a handler for + * @rx_handler: receive handler to register + * @rx_handler_data: data pointer that is used by rx handler + * + * Register a receive hander for a device. This handler will then be + * called from netif_receive_skb. A negative errno code is returned + * on a failure. + * + * The caller must hold the rtnl_mutex. + */ +int netdev_rx_handler_register(struct net_device *dev, + rx_handler_func_t *rx_handler, + void *rx_handler_data) +{ + ASSERT_RTNL(); + + if (dev->rx_handler) + return -EBUSY; + + rcu_assign_pointer(dev->rx_handler_data, rx_handler_data); + rcu_assign_pointer(dev->rx_handler, rx_handler); + + return 0; +} +EXPORT_SYMBOL_GPL(netdev_rx_handler_register); + +/** + * netdev_rx_handler_unregister - unregister receive handler + * @dev: device to unregister a handler from + * + * Unregister a receive hander from a device. + * + * The caller must hold the rtnl_mutex. + */ +void netdev_rx_handler_unregister(struct net_device *dev) +{ + + ASSERT_RTNL(); + rcu_assign_pointer(dev->rx_handler, NULL); + rcu_assign_pointer(dev->rx_handler_data, NULL); +} +EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); + + + +/** * netif_receive_skb - process receive buffer from network * @skb: buffer to process * @@ -2301,9 +2359,15 @@ * NET_RX_SUCCESS: no congestion * NET_RX_DROP: packet was dropped */ + +#ifdef CONFIG_LTQ_BR_OPT +int __bridge netif_receive_skb(struct sk_buff *skb) +#else int netif_receive_skb(struct sk_buff *skb) +#endif { struct packet_type *ptype, *pt_prev; + rx_handler_func_t *rx_handler; struct net_device *orig_dev; struct net_device *null_or_orig; int ret = NET_RX_DROP; @@ -2316,11 +2380,16 @@ return NET_RX_SUCCESS; /* if we've gotten here through NAPI, check netpoll */ +#ifdef CONFIG_MAPPING + if (skb->dev) +#endif if (netpoll_receive_skb(skb)) return NET_RX_DROP; if (!skb->iif) skb->iif = skb->dev->ifindex; + if (!skb->input_dev) + skb->input_dev = skb->dev; null_or_orig = NULL; orig_dev = skb->dev; @@ -2364,12 +2433,40 @@ ncls: #endif - skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); - if (!skb) +#ifdef CONFIG_AVM_PA + if (avm_pa_dev_receive(AVM_PA_DEVINFO(skb->dev), skb) == 0) { + ret = NET_RX_SUCCESS; goto out; - skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev); - if (!skb) + } +#endif + + if (avm_early_recvhook && (*avm_early_recvhook)(skb)) { + /* + * paket consumed by hook + */ + ret = NET_RX_SUCCESS; + goto out; + } + + /* Handle special case of bridge or macvlan */ + rx_handler = rcu_dereference(skb->dev->rx_handler); + if (rx_handler) { + if (pt_prev) { + ret = deliver_skb(skb, pt_prev, orig_dev); + pt_prev = NULL; + } + skb = rx_handler(skb); + if (!skb) + goto out; + } + + if (avm_recvhook && (*avm_recvhook)(skb)) { + /* + * paket consumed by hook + */ + ret = NET_RX_SUCCESS; goto out; + } type = skb->protocol; list_for_each_entry_rcu(ptype, @@ -2722,7 +2819,11 @@ } EXPORT_SYMBOL(napi_gro_frags); +#ifdef CONFIG_LTQ_BR_OPT +static int __bridge process_backlog(struct napi_struct *napi, int quota) +#else static int process_backlog(struct napi_struct *napi, int quota) +#endif { int work = 0; struct softnet_data *queue = &__get_cpu_var(softnet_data); @@ -3645,10 +3746,10 @@ unsigned char addr_type) { struct netdev_hw_addr *ha; - unsigned char type; + /*--- unsigned char type; ---*/ list_for_each_entry(ha, &from_list->list, list) { - type = addr_type ? addr_type : ha->type; + /*--- type = addr_type ? addr_type : ha->type; ---*/ __hw_addr_del(to_list, ha->addr, addr_len, addr_type); } } @@ -4270,10 +4371,15 @@ if (!netif_device_present(dev)) return -ENODEV; err = ops->ndo_set_mac_address(dev, sa); - if (!err) - call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + /* AVM: backport: fbdeca2d7753aa1ab929aeb77ccc46489eed02b9 + * + * net: add address assign type "SET" */ + if (err) + return err; + dev->addr_assign_type = NET_ADDR_SET; + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); add_device_randomness(dev->dev_addr, dev->addr_len); - return err; + return 0; } EXPORT_SYMBOL(dev_set_mac_address); @@ -4433,6 +4539,11 @@ cmd == SIOCSMIIREG || cmd == SIOCBRADDIF || cmd == SIOCBRDELIF || +#ifdef CONFIG_IFX_IGMP_SNOOPING + cmd == SIOCBRADDMGREC || + cmd == SIOCBRDELMGREC || + cmd == SIOCBRSETROUTERPORT || +#endif cmd == SIOCSHWTSTAMP || cmd == SIOCWANDEV) { err = -EOPNOTSUPP; @@ -4453,6 +4564,33 @@ * This function handles all "interface"-type I/O control requests. The actual * 'doing' part of this is dev_ifsioc above. */ +void release_offload_lock(int in_offload_lock){ + if (in_offload_lock) + rtnl_offload_read_unlock(); +} + +int acquire_offload_lock(struct net *net, const char *name){ + struct net_device *dev; + int need_lock; + + read_lock(&dev_base_lock); + dev = __dev_get_by_name(net, name); + need_lock = ( dev && (dev->priv_flags & IFF_AVM_WLAN_OFFLOAD_DEVICE)); + read_unlock(&dev_base_lock); + + if (need_lock){ + rtnl_offload_read_lock(); + /* + * now we have to wait for for wasp device to become completely functional + * queue_state: + * - dev->flags: IFF_MULTICAST, IFF_BROADCAST, IFF_UP + * - dev->state: __LINK_STATE_START, __LINK_STATE_PRESENT + */ + wait_for_link_to_offload_cpu(); + } + + return need_lock; +} /** * dev_ioctl - network device ioctl @@ -4471,6 +4609,7 @@ struct ifreq ifr; int ret; char *colon; + int in_offload_lock = 0; /* One special case: SIOCGIFCONF takes ifconf argument and requires shared lock, because it sleeps writing @@ -4515,9 +4654,11 @@ case SIOCGIFINDEX: case SIOCGIFTXQLEN: dev_load(net, ifr.ifr_name); + in_offload_lock = acquire_offload_lock(net, ifr.ifr_name); read_lock(&dev_base_lock); ret = dev_ifsioc_locked(net, &ifr, cmd); read_unlock(&dev_base_lock); + release_offload_lock(in_offload_lock); if (!ret) { if (colon) *colon = ':'; @@ -4529,9 +4670,11 @@ case SIOCETHTOOL: dev_load(net, ifr.ifr_name); + in_offload_lock = acquire_offload_lock(net, ifr.ifr_name); rtnl_lock(); ret = dev_ethtool(net, &ifr); rtnl_unlock(); + release_offload_lock(in_offload_lock); if (!ret) { if (colon) *colon = ':'; @@ -4553,9 +4696,11 @@ if (!capable(CAP_NET_ADMIN)) return -EPERM; dev_load(net, ifr.ifr_name); + in_offload_lock = acquire_offload_lock(net, ifr.ifr_name); rtnl_lock(); ret = dev_ifsioc(net, &ifr, cmd); rtnl_unlock(); + release_offload_lock(in_offload_lock); if (!ret) { if (colon) *colon = ':'; @@ -4588,6 +4733,11 @@ case SIOCBONDCHANGEACTIVE: case SIOCBRADDIF: case SIOCBRDELIF: +#ifdef CONFIG_IFX_IGMP_SNOOPING + case SIOCBRADDMGREC: + case SIOCBRDELMGREC: + case SIOCBRSETROUTERPORT: +#endif case SIOCSHWTSTAMP: if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -4595,9 +4745,11 @@ case SIOCBONDSLAVEINFOQUERY: case SIOCBONDINFOQUERY: dev_load(net, ifr.ifr_name); + in_offload_lock = acquire_offload_lock(net, ifr.ifr_name); rtnl_lock(); ret = dev_ifsioc(net, &ifr, cmd); rtnl_unlock(); + release_offload_lock(in_offload_lock); return ret; case SIOCGIFMEM: @@ -4617,17 +4769,23 @@ (cmd >= SIOCDEVPRIVATE && cmd <= SIOCDEVPRIVATE + 15)) { dev_load(net, ifr.ifr_name); + in_offload_lock = acquire_offload_lock(net, ifr.ifr_name); rtnl_lock(); ret = dev_ifsioc(net, &ifr, cmd); rtnl_unlock(); + release_offload_lock(in_offload_lock); if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) ret = -EFAULT; return ret; } /* Take care of Wireless Extensions */ - if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) - return wext_handle_ioctl(net, &ifr, cmd, arg); + if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST){ + in_offload_lock = acquire_offload_lock(net, ifr.ifr_name); + ret = wext_handle_ioctl(net, &ifr, cmd, arg); + release_offload_lock(in_offload_lock); + return ret; + } return -EINVAL; } } @@ -4645,8 +4803,15 @@ { static int ifindex; for (;;) { +//der FUSIV Source kommt nicht klar mit DEV Counter > 255 +//Absturz bei WLAN Autotest +#ifdef CONFIG_MACH_FUSIV + if (++ifindex >= 256) + ifindex = 1; +#else if (++ifindex <= 0) ifindex = 1; +#endif if (!__dev_get_by_index(net, ifindex)) return ifindex; } @@ -5083,6 +5248,9 @@ WARN_ON(dev->ip_ptr); WARN_ON(dev->ip6_ptr); WARN_ON(dev->dn_ptr); +#ifdef CONFIG_AVM_PA + avm_pa_dev_unregister(AVM_PA_DEVINFO(dev)); +#endif if (dev->destructor) dev->destructor(dev); @@ -5205,6 +5373,9 @@ INIT_LIST_HEAD(&dev->napi_list); dev->priv_flags = IFF_XMIT_DST_RELEASE; +#ifdef CONFIG_AVM_PA + avm_pa_dev_init(AVM_PA_DEVINFO(dev)); +#endif setup(dev); strcpy(dev->name, name); return dev;