static struct vport *netdev_create(const struct vport_parms *parms) { struct vport *vport; struct netdev_vport *netdev_vport; int err; vport = ovs_vport_alloc(sizeof(struct netdev_vport), &ovs_netdev_vport_ops, parms); if (IS_ERR(vport)) { err = PTR_ERR(vport); goto error; } netdev_vport = netdev_vport_priv(vport); netdev_vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), parms->name); if (!netdev_vport->dev) { err = -ENODEV; goto error_free_vport; } if (netdev_vport->dev->flags & IFF_LOOPBACK || netdev_vport->dev->type != ARPHRD_ETHER || ovs_is_internal_dev(netdev_vport->dev)) { err = -EINVAL; goto error_put; } rtnl_lock(); err = netdev_master_upper_dev_link(netdev_vport->dev, get_dpdev(vport->dp)); if (err) goto error_unlock; err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport); if (err) goto error_master_upper_dev_unlink; dev_set_promiscuity(netdev_vport->dev, 1); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) dev_disable_lro(netdev_vport->dev); #endif netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; rtnl_unlock(); netdev_init(); return vport; error_master_upper_dev_unlink: netdev_upper_dev_unlink(netdev_vport->dev, get_dpdev(vport->dp)); error_unlock: rtnl_unlock(); error_put: dev_put(netdev_vport->dev); error_free_vport: ovs_vport_free(vport); error: return ERR_PTR(err); }
static int netif_drop_packets_enable(netif_info *pt_netif) { int ret = 0; ret = netdev_rx_handler_register(pt_netif->ndev, drop_packet, pt_netif); if (ret) { DBG_PRINT("Error %d calling netdev_rx_handler_register\n", ret); goto out; } #ifdef CONFIG_NETPOLL DBG_PRINT("==CONFIG_NETPOLL"); /* no effection for net_device on which netpoll have already been set up */ pt_netif->ndev->priv_flags |= IFF_DISABLE_NETPOLL; smp_wmb(); if (rcu_dereference(pt_netif->ndev->npinfo)) { /* netpoll already set up on this dev, rollback previous operations and return fail */ netif_drop_packets_disable(pt_netif); ret = -EBUSY; goto out; } #endif DBG_PRINT("=="); out: return ret; }
static int rmnet_register_real_device(struct net_device *real_dev) { struct rmnet_port *port; int rc; ASSERT_RTNL(); if (rmnet_is_real_dev_registered(real_dev)) return 0; port = kzalloc(sizeof(*port), GFP_ATOMIC); if (!port) return -ENOMEM; port->dev = real_dev; rc = netdev_rx_handler_register(real_dev, rmnet_rx_handler, port); if (rc) { kfree(port); return -EBUSY; } /* hold on to real dev for MAP data */ dev_hold(real_dev); netdev_dbg(real_dev, "registered with rmnet\n"); return 0; }
static struct vport *netdev_create(const struct vport_parms *parms) { struct vport *vport; struct netdev_vport *netdev_vport; int err; vport = ovs_vport_alloc(sizeof(struct netdev_vport), &ovs_netdev_vport_ops, parms); if (IS_ERR(vport)) { err = PTR_ERR(vport); goto error; } netdev_vport = netdev_vport_priv(vport); netdev_vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), parms->name); if (!netdev_vport->dev) { err = -ENODEV; goto error_free_vport; } if (netdev_vport->dev->flags & IFF_LOOPBACK || netdev_vport->dev->type != ARPHRD_ETHER || ovs_is_internal_dev(netdev_vport->dev)) { err = -EINVAL; goto error_put; } rtnl_lock(); #ifdef HAVE_RHEL_OVS_HOOK rcu_assign_pointer(netdev_vport->dev->ax25_ptr, vport); atomic_inc(&nr_bridges); rcu_assign_pointer(openvswitch_handle_frame_hook, netdev_frame_hook); #else err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport); if (err) goto error_unlock; #endif dev_set_promiscuity(netdev_vport->dev, 1); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) dev_disable_lro(netdev_vport->dev); #endif netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; rtnl_unlock(); return vport; #ifndef HAVE_RHEL_OVS_HOOK error_unlock: #endif rtnl_unlock(); error_put: dev_put(netdev_vport->dev); error_free_vport: ovs_vport_free(vport); error: return ERR_PTR(err); }
/* Setup device to be added to the HSR bridge. */ static int hsr_portdev_setup(struct net_device *dev, struct hsr_port *port) { int res; dev_hold(dev); res = dev_set_promiscuity(dev, 1); if (res) goto fail_promiscuity; /* FIXME: * What does net device "adjacency" mean? Should we do * res = netdev_master_upper_dev_link(port->dev, port->hsr->dev); ? */ res = netdev_rx_handler_register(dev, hsr_handle_frame, port); if (res) goto fail_rx_handler; dev_disable_lro(dev); return 0; fail_rx_handler: dev_set_promiscuity(dev, -1); fail_promiscuity: dev_put(dev); return res; }
static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev) { int ret; /* register the packet handler for slave ports */ ret = netdev_rx_handler_register(port_dev, vrf_handle_frame, dev); if (ret) { netdev_err(port_dev, "Device %s failed to register rx_handler\n", port_dev->name); goto out_fail; } ret = netdev_master_upper_dev_link(port_dev, dev, NULL, NULL); if (ret < 0) goto out_unregister; port_dev->priv_flags |= IFF_L3MDEV_SLAVE; cycle_netdev(port_dev); return 0; out_unregister: netdev_rx_handler_unregister(port_dev); out_fail: return ret; }
/* * 重要!通过相应的参数进行网络设备的注册 * 何时调用? */ static struct vport *netdev_create(const struct vport_parms *parms) { struct vport *vport; struct netdev_vport *netdev_vport; // 看vport_netdev.h中的定义 int err; //根据具体的ovs_netdev_vport_ops和参数构造一个vport // 第一个参数代表私有数据的大小,这里正是要放struct netdev_vport vport = ovs_vport_alloc(sizeof(struct netdev_vport), &ovs_netdev_vport_ops, parms); if (IS_ERR(vport)) { err = PTR_ERR(vport); goto error; } netdev_vport = netdev_vport_priv(vport); netdev_vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), parms->name); if (!netdev_vport->dev) { err = -ENODEV; goto error_free_vport; } if (netdev_vport->dev->flags & IFF_LOOPBACK || netdev_vport->dev->type != ARPHRD_ETHER || ovs_is_internal_dev(netdev_vport->dev)) { err = -EINVAL; goto error_put; } /* 重要!就是设置net_device两个字段 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 */ err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport); if (err) goto error_put; dev_set_promiscuity(netdev_vport->dev, 1); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) dev_disable_lro(netdev_vport->dev); #endif netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; return vport; error_put: dev_put(netdev_vport->dev); error_free_vport: ovs_vport_free(vport); error: return ERR_PTR(err); }
static int netdev_attach(struct vport *vport) { struct netdev_vport *netdev_vport = netdev_vport_priv(vport); int err; err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport); if (err) return err; dev_set_promiscuity(netdev_vport->dev, 1); dev_disable_lro(netdev_vport->dev); netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; return 0; }
struct vport *ovs_netdev_link(struct vport *vport, const char *name) { int err; vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), name); if (!vport->dev) { err = -ENODEV; goto error_free_vport; } if (vport->dev->flags & IFF_LOOPBACK || (vport->dev->type != ARPHRD_ETHER && vport->dev->type != ARPHRD_NONE) || ovs_is_internal_dev(vport->dev)) { err = -EINVAL; goto error_put; } rtnl_lock(); err = netdev_master_upper_dev_link(vport->dev, get_dpdev(vport->dp), NULL, NULL, NULL); if (err) goto error_unlock; err = netdev_rx_handler_register(vport->dev, netdev_frame_hook, vport); if (err) goto error_master_upper_dev_unlink; dev_disable_lro(vport->dev); dev_set_promiscuity(vport->dev, 1); vport->dev->priv_flags |= IFF_OVS_DATAPATH; rtnl_unlock(); return vport; error_master_upper_dev_unlink: netdev_upper_dev_unlink(vport->dev, get_dpdev(vport->dp)); error_unlock: rtnl_unlock(); error_put: dev_put(vport->dev); error_free_vport: ovs_vport_free(vport); return ERR_PTR(err); }
/* Ask the Linux RX subsystem to intercept (or stop intercepting) * the packets incoming from the interface attached to 'na'. */ int netmap_catch_rx(struct netmap_adapter *na, int intercept) { #ifndef NETMAP_LINUX_HAVE_RX_REGISTER return 0; #else /* HAVE_RX_REGISTER */ struct ifnet *ifp = na->ifp; if (intercept) { return -netdev_rx_handler_register(na->ifp, &linux_generic_rx_handler, na); } else { netdev_rx_handler_unregister(ifp); return 0; } #endif /* HAVE_RX_REGISTER */ }
static struct vport *netdev_create(const struct vport_parms *parms) { struct vport *vport; struct netdev_vport *netdev_vport; int err; vport = ovs_vport_alloc(sizeof(struct netdev_vport), &ovs_netdev_vport_ops, parms); if (IS_ERR(vport)) { err = PTR_ERR(vport); goto error; } netdev_vport = netdev_vport_priv(vport); netdev_vport->dev = dev_get_by_name(&init_net, parms->name); if (!netdev_vport->dev) { err = -ENODEV; goto error_free_vport; } if (netdev_vport->dev->flags & IFF_LOOPBACK || netdev_vport->dev->type != ARPHRD_ETHER || ovs_is_internal_dev(netdev_vport->dev)) { err = -EINVAL; goto error_put; } err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport); if (err) goto error_put; dev_set_promiscuity(netdev_vport->dev, 1); netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; return vport; error_put: dev_put(netdev_vport->dev); error_free_vport: ovs_vport_free(vport); error: return ERR_PTR(err); }
/** * rmnet_associate_network_device() - Associate network device * @dev: Device to register with RmNet data * * Typically used on physical network devices. Registers RX handler and private * metadata structures. * * Return: * - RMNET_CONFIG_OK if successful * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null * - RMNET_CONFIG_INVALID_REQUEST if the device to be associated is a vnd * - RMNET_CONFIG_DEVICE_IN_USE if dev rx_handler is already filled * - RMNET_CONFIG_DEVICE_IN_USE if netdev_rx_handler_register() fails */ int rmnet_associate_network_device(struct net_device *dev) { struct rmnet_phys_ep_conf_s *config; int rc; ASSERT_RTNL(); LOGL("(%s);\n", dev->name); if (!dev) return RMNET_CONFIG_NO_SUCH_DEVICE; if (_rmnet_is_physical_endpoint_associated(dev)) { LOGM("%s is already regestered", dev->name); return RMNET_CONFIG_DEVICE_IN_USE; } if (rmnet_vnd_is_vnd(dev)) { LOGM("%s is a vnd", dev->name); return RMNET_CONFIG_INVALID_REQUEST; } config = (struct rmnet_phys_ep_conf_s *) kmalloc(sizeof(struct rmnet_phys_ep_conf_s), GFP_ATOMIC); if (!config) return RMNET_CONFIG_NOMEM; memset(config, 0, sizeof(struct rmnet_phys_ep_conf_s)); config->dev = dev; spin_lock_init(&config->agg_lock); rc = netdev_rx_handler_register(dev, rmnet_rx_handler, config); if (rc) { LOGM("netdev_rx_handler_register returns %d", rc); kfree(config); return RMNET_CONFIG_DEVICE_IN_USE; } /* Explicitly hold a reference to the device */ dev_hold(dev); trace_rmnet_associate(dev); return RMNET_CONFIG_OK; }
int __init init( void ) { int err = 0; struct priv *priv; char ifstr[ 40 ]; sprintf( ifstr, "%s%s", ifname, "%d" ); #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)) child = alloc_netdev( sizeof( struct priv ), ifstr, setup ); #else child = alloc_netdev( sizeof( struct priv ), ifstr, NET_NAME_UNKNOWN, setup ); #endif if( child == NULL ) { ERR( "%s: allocate error", THIS_MODULE->name ); return -ENOMEM; } priv = netdev_priv( child ); priv->parent = __dev_get_by_name( &init_net, link ); // parent interface if( !priv->parent ) { ERR( "%s: no such net: %s", THIS_MODULE->name, link ); err = -ENODEV; goto err; } if( priv->parent->type != ARPHRD_ETHER && priv->parent->type != ARPHRD_LOOPBACK ) { ERR( "%s: illegal net type", THIS_MODULE->name ); err = -EINVAL; goto err; } /* also, and clone its IP, MAC and other information */ memcpy( child->dev_addr, priv->parent->dev_addr, ETH_ALEN ); memcpy( child->broadcast, priv->parent->broadcast, ETH_ALEN ); if( ( err = dev_alloc_name( child, child->name ) ) ) { ERR( "%s: allocate name, error %i", THIS_MODULE->name, err ); err = -EIO; goto err; } register_netdev( child ); rtnl_lock(); netdev_rx_handler_register( priv->parent, &handle_frame, NULL ); rtnl_unlock(); LOG( "module %s loaded", THIS_MODULE->name ); LOG( "%s: create link %s", THIS_MODULE->name, child->name ); LOG( "%s: registered rx handler for %s", THIS_MODULE->name, priv->parent->name ); return 0; err: free_netdev( child ); return err; }
static int macvtap_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { struct macvtap_dev *vlantap = netdev_priv(dev); int err; INIT_LIST_HEAD(&vlantap->tap.queue_list); /* Since macvlan supports all offloads by default, make * tap support all offloads also. */ vlantap->tap.tap_features = TUN_OFFLOADS; /* Register callbacks for rx/tx drops accounting and updating * net_device features */ vlantap->tap.count_tx_dropped = macvtap_count_tx_dropped; vlantap->tap.count_rx_dropped = macvtap_count_rx_dropped; vlantap->tap.update_features = macvtap_update_features; err = netdev_rx_handler_register(dev, tap_handle_frame, &vlantap->tap); if (err) return err; /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ err = macvlan_common_newlink(src_net, dev, tb, data); if (err) { netdev_rx_handler_unregister(dev); return err; } vlantap->tap.dev = vlantap->vlan.dev; return 0; }
static int __init rh_init(void) { int rc = 0, err; int i; pr_info("rxhook (v%s) is loaded\n", RXHOOK_VERSION); rh = kmalloc(sizeof(struct rh_dev), GFP_KERNEL); if (rh == 0) { pr_info("fail to kmalloc: *rh_dev\n"); rc = -1; goto out; } rh->dev = dev_get_by_name(&init_net, ifname); if (!rh->dev) { pr_err("Could not find %s\n", ifname); rc = -1; goto out; } rh->cpu = smp_processor_id(); pr_info("cpuid: %d\n", rh->cpu); // register rtnl_lock(); err = netdev_rx_handler_register(rh->dev, rh_handle_frame, rh); rtnl_unlock(); if (err) { pr_err("%s failed to register rx_handler\n", ifname); } for(i = 0; i < 10; i++) pps[i] = 0; out: return rc; }
static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev) { struct slave *slave = kzalloc(sizeof(*slave), GFP_KERNEL); struct net_vrf *vrf = netdev_priv(dev); struct slave_queue *queue = &vrf->queue; int ret = -ENOMEM; if (!slave) goto out_fail; slave->dev = port_dev; /* register the packet handler for slave ports */ ret = netdev_rx_handler_register(port_dev, vrf_handle_frame, dev); if (ret) { netdev_err(port_dev, "Device %s failed to register rx_handler\n", port_dev->name); goto out_fail; } ret = netdev_master_upper_dev_link(port_dev, dev); if (ret < 0) goto out_unregister; port_dev->priv_flags |= IFF_L3MDEV_SLAVE; __vrf_insert_slave(queue, slave); cycle_netdev(port_dev); return 0; out_unregister: netdev_rx_handler_unregister(port_dev); out_fail: kfree(slave); return ret; }
/** * rmnet_associate_network_device() - Associate network device * @dev: Device to register with RmNet data * * Typically used on physical network devices. Registers RX handler and private * metadata structures. * * Return: * - RMNET_CONFIG_OK if successful * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null * - RMNET_CONFIG_DEVICE_IN_USE if dev rx_handler is already filled * - RMNET_CONFIG_DEVICE_IN_USE if netdev_rx_handler_register() fails */ int rmnet_associate_network_device(struct net_device *dev) { struct rmnet_phys_ep_conf_s *config; int rc; ASSERT_RTNL(); LOGL("%s(%s);", __func__, dev->name); if (!dev) return RMNET_CONFIG_NO_SUCH_DEVICE; if (_rmnet_is_physical_endpoint_associated(dev)) { LOGM("%s(): %s is already regestered\n", __func__, dev->name); return RMNET_CONFIG_DEVICE_IN_USE; } config = (struct rmnet_phys_ep_conf_s *) kmalloc(sizeof(struct rmnet_phys_ep_conf_s), GFP_ATOMIC); if (!config) return RMNET_CONFIG_NOMEM; memset(config, 0, sizeof(struct rmnet_phys_ep_conf_s)); config->dev = dev; spin_lock_init(&config->agg_lock); rc = netdev_rx_handler_register(dev, rmnet_rx_handler, config); if (rc) { LOGM("%s(): netdev_rx_handler_register returns %d\n", __func__, rc); kfree(config); return RMNET_CONFIG_DEVICE_IN_USE; } return RMNET_CONFIG_OK; }
/* * register an rx handler which will bypass all vrouter processing. Helpful * at the time of vrouter soft reset. For kernels that does not support rx * handler tap, the logic is handled in linux_rx_handler, albeit in an * inefficient way (but works :) */ void vhost_tap_phys(struct net_device *vdev, struct net_device *pdev) { struct vhost_priv *vp; if (!vdev || !pdev) return; vp = netdev_priv(vdev); /* * with vhost_attach_phys, it is possible that everything was OK except * that the physical went out and came back. if that is the case, do not * tap here */ if (vp->vp_vifp) goto exit_tap_phys; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) /* * it can so happen (unlikely) that vhost is deleted from vrouter * before the physical, in which case we will have to unregister * the rx handler in physical and install the vhost_rx_handler */ if (rcu_dereference(pdev->rx_handler) == linux_rx_handler) netdev_rx_handler_unregister(pdev); if (!rcu_dereference(pdev->rx_handler)) netdev_rx_handler_register(pdev, vhost_rx_handler, (void *)vdev); #else vr_set_vif_ptr(pdev, &vr_reset_interface); #endif exit_tap_phys: return; }
struct netpoll_wrapper *netpoll_wrapper_create(const char *pDeviceName, int localPort, const char *pOptionalLocalIp) { struct net_device *pDevice; struct netpoll_wrapper *pResult; int localIp; int err; if (!pDeviceName || !localPort) { printk(KERN_ERR "kgdboe: cannot create a netpoll wrapper without a device name\n"); return NULL; } pDevice = dev_get_by_name(&init_net, pDeviceName); if (!pDevice) { printk(KERN_ERR "kgdboe: Cannot find network device by name: %s\n", pDeviceName); return NULL; } if (pOptionalLocalIp) { localIp = in_aton(pOptionalLocalIp); if (!localIp) { printk(KERN_ERR "kgdboe: Invalid local IP: %s\n", pOptionalLocalIp); return NULL; } } else { if (!pDevice->ip_ptr) { printk(KERN_ERR "kgdboe: %s does not have an in_device associated. Cannot get default IP address.\n", pDeviceName); return NULL; } if (!pDevice->ip_ptr->ifa_list) { printk(KERN_ERR "kgdboe: %s does not have a in_ifaddr struct associated. Cannot get default IP address.\n", pDeviceName); return NULL; } localIp = pDevice->ip_ptr->ifa_list->ifa_local; } pResult = (struct netpoll_wrapper *)kmalloc(sizeof(struct netpoll_wrapper), GFP_KERNEL); if (!pResult) { printk(KERN_ERR "kgdboe: cannot allocate memory for netpoll wrapper\n"); return NULL; } memset(pResult, 0, sizeof(*pResult)); #ifdef NETPOLL_POLL_DEV_USABLE pResult->netpoll_poll_dev = (void(*)(struct net_device *))kallsyms_lookup_name("netpoll_poll_dev"); if (!pResult->netpoll_poll_dev) { printk(KERN_ERR "kgdboe: Cannot find netpoll_poll_dev(). Aborting.\n"); netpoll_wrapper_free(pResult); return NULL; } #else pResult->zap_completion_queue = (void(*)(void))kallsyms_lookup_name("zap_completion_queue"); if (!pResult->zap_completion_queue) { printk(KERN_ERR "kgdboe: Cannot find zap_completion_queue(). Aborting.\n"); netpoll_wrapper_free(pResult); return NULL; } #endif rtnl_lock(); err = netdev_rx_handler_register(pDevice, netpoll_wrapper_rx_handler, pResult); rtnl_unlock(); if (err < 0) { printk(KERN_ERR "kgdboe: Failed to register rx handler for %s, code %d\n", pDeviceName, err); netpoll_wrapper_free(pResult); return NULL; } register_tracepoint_wrapper(netif_receive_skb, hook_receive_skb, pResult); pResult->tracepoint_registered = true; pResult->pDeviceWithHandler = pDevice; strncpy(pResult->netpoll_obj.dev_name, pDeviceName, sizeof(pResult->netpoll_obj.dev_name)); pResult->netpoll_obj.name = "kgdboe"; pResult->netpoll_obj.local_port = localPort; memset(pResult->netpoll_obj.remote_mac, 0xFF, sizeof(pResult->netpoll_obj.remote_mac)); err = netpoll_setup(&pResult->netpoll_obj); if (err < 0) { printk(KERN_ERR "kgdboe: Failed to setup netpoll for %s, code %d\n", pDeviceName, err); netpoll_wrapper_free(pResult); return NULL; } pResult->netpoll_initialized = true; return pResult; }
static struct vport *netdev_create(const struct vport_parms *parms) { struct vport *vport; struct netdev_vport *netdev_vport; int err; vport = ovs_vport_alloc(sizeof(struct netdev_vport), &ovs_netdev_vport_ops, parms); if (IS_ERR(vport)) { err = PTR_ERR(vport); goto error; } netdev_vport = netdev_vport_priv(vport); //TODO:这里直接获取, 原因 netdev_vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), parms->name); if (!netdev_vport->dev) { err = -ENODEV; goto error_free_vport; } if (netdev_vport->dev->flags & IFF_LOOPBACK || netdev_vport->dev->type != ARPHRD_ETHER || ovs_is_internal_dev(netdev_vport->dev)) { err = -EINVAL; goto error_put; } rtnl_lock(); /** * netdev_master_upper_dev_link - Add a master link to the upper device * @dev: device * @upper_dev: new upper device * * Adds a link to device which is upper to this one. In this case, only * one master upper device can be linked, although other non-master devices * might be linked as well. The caller must hold the RTNL lock. * On a failure a negative errno code is returned. On success the reference * counts are adjusted and the function returns zero. */ err = netdev_master_upper_dev_link(netdev_vport->dev, get_dpdev(vport->dp)); if (err) goto error_unlock; /** * 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 handler 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. * * For a general description of rx_handler, see enum rx_handler_result. */ err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport); if (err) goto error_master_upper_dev_unlink; dev_set_promiscuity(netdev_vport->dev, 1); netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; rtnl_unlock(); return vport; error_master_upper_dev_unlink: netdev_upper_dev_unlink(netdev_vport->dev, get_dpdev(vport->dp)); error_unlock: rtnl_unlock(); error_put: dev_put(netdev_vport->dev); error_free_vport: ovs_vport_free(vport); error: return ERR_PTR(err); }