--- zzzz-none-000/linux-5.15.111/net/openvswitch/vport-netdev.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/net/openvswitch/vport-netdev.c 2024-02-07 10:23:30.000000000 +0000 @@ -3,6 +3,16 @@ * Copyright (c) 2007-2012 Nicira, Inc. */ +/* + * Includes Inango Systems Ltd’s changes/modifications dated: 2021. + * Changed/modified portions - Copyright (c) 2021 , Inango Systems Ltd. + */ + +/* + Includes MaxLinear's changes dated: 2021, 2022, 2023. + Changed portions - Copyright 2021-2023 MaxLinear, Inc. +*/ + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include @@ -70,12 +80,19 @@ struct vport *local; local = ovs_vport_ovsl(dp, OVSP_LOCAL); + BUG_ON(!local); return local->dev; } - +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT +struct vport *ovs_netdev_link(struct vport *vport, const char *name, const char *bridgeName) +#else struct vport *ovs_netdev_link(struct vport *vport, const char *name) +#endif { int err; +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT + struct vport *bridge = NULL; +#endif vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), name); if (!vport->dev) { @@ -91,27 +108,65 @@ goto error_put; } +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT + /* Create symlink from /sys/class/net//master to + * /sys/class/net/. */ + if (!ovs_is_internal_dev(vport->dev)) { + if (bridgeName != NULL && *bridgeName) + { + bridge = get_vport_by_bridge(vport->dp, bridgeName); + if (bridge == NULL) { + err = -EINVAL; + goto error_put; + } + } + } +#endif + rtnl_lock(); + +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT + vport->dev->priv_flags |= IFF_OVS_DATAPATH; +#else err = netdev_master_upper_dev_link(vport->dev, get_dpdev(vport->dp), NULL, NULL, NULL); if (err) goto error_unlock; +#endif err = netdev_rx_handler_register(vport->dev, netdev_frame_hook, vport); if (err) +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT + goto error_unlock; +#else goto error_master_upper_dev_unlink; +#endif +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT + err = netdev_master_upper_dev_link(vport->dev, + bridge ? bridge->dev : get_dpdev(vport->dp), + NULL, NULL, NULL); + if (err) + goto error_rx_handler_unregister; +#endif dev_disable_lro(vport->dev); dev_set_promiscuity(vport->dev, 1); +#ifndef CONFIG_OPENVSWITCH_BRCOMPAT vport->dev->priv_flags |= IFF_OVS_DATAPATH; +#endif rtnl_unlock(); return vport; +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT +error_rx_handler_unregister: + netdev_rx_handler_unregister(vport->dev); +#else error_master_upper_dev_unlink: netdev_upper_dev_unlink(vport->dev, get_dpdev(vport->dp)); +#endif error_unlock: rtnl_unlock(); error_put: @@ -130,7 +185,11 @@ if (IS_ERR(vport)) return vport; +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT + return ovs_netdev_link(vport, parms->name, parms->bridge_name); +#else return ovs_netdev_link(vport, parms->name); +#endif } static void vport_netdev_free(struct rcu_head *rcu) @@ -142,9 +201,23 @@ ovs_vport_free(vport); } +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT +static int ovs_brcompat_port_destroy(struct vport *vport) +{ + if (ovs_dp_br_bridge_port_setup) { + return ovs_dp_br_bridge_port_setup(NULL, vport, 0); + } + + return EOPNOTSUPP; +} +#endif + void ovs_netdev_detach_dev(struct vport *vport) { ASSERT_RTNL(); +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT + ovs_brcompat_port_destroy(vport); +#endif vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; netdev_rx_handler_unregister(vport->dev); netdev_upper_dev_unlink(vport->dev, @@ -159,9 +232,64 @@ ovs_netdev_detach_dev(vport); rtnl_unlock(); +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT + OVS_LOG_DBG("vport %s successfully destroyed \n", vport->dev->name); +#endif call_rcu(&vport->rcu, vport_netdev_free); } +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT +int ovs_netdev_set_addr(struct vport *vport, const unsigned char *addr) +{ + struct sockaddr sa; + + sa.sa_family = ARPHRD_ETHER; + memcpy(sa.sa_data, addr, ETH_ALEN); + + return dev_set_mac_address(vport->dev, &sa, NULL); +} + +const char *ovs_netdev_get_name(const struct vport *vport) +{ + return vport->dev->name; +} + +const unsigned char *ovs_netdev_get_addr(const struct vport *vport) +{ + return vport->dev->dev_addr; +} + +struct kobject *ovs_netdev_get_kobj(const struct vport *vport) +{ + return &vport->dev->dev.kobj; +} + +unsigned ovs_netdev_get_dev_flags(const struct vport *vport) +{ + return dev_get_flags(vport->dev); +} + +int ovs_netdev_is_running(const struct vport *vport) +{ + return netif_running(vport->dev); +} + +unsigned char ovs_netdev_get_operstate(const struct vport *vport) +{ + return vport->dev->operstate; +} + +int ovs_netdev_get_ifindex(const struct vport *vport) +{ + return vport->dev->ifindex; +} + +int ovs_netdev_get_mtu(const struct vport *vport) +{ + return vport->dev->mtu; +} +#endif /* CONFIG_OPENVSWITCH_BRCOMPAT */ + void ovs_netdev_tunnel_destroy(struct vport *vport) { rtnl_lock(); @@ -191,11 +319,25 @@ else return NULL; } +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT +EXPORT_SYMBOL(ovs_netdev_get_vport); +#endif static struct vport_ops ovs_netdev_vport_ops = { .type = OVS_VPORT_TYPE_NETDEV, .create = netdev_create, .destroy = netdev_destroy, +#ifdef CONFIG_OPENVSWITCH_BRCOMPAT + .set_addr = ovs_netdev_set_addr, + .get_name = ovs_netdev_get_name, + .get_addr = ovs_netdev_get_addr, + .get_kobj = ovs_netdev_get_kobj, + .get_dev_flags = ovs_netdev_get_dev_flags, + .is_running = ovs_netdev_is_running, + .get_operstate = ovs_netdev_get_operstate, + .get_ifindex = ovs_netdev_get_ifindex, + .get_mtu = ovs_netdev_get_mtu, +#endif .send = dev_queue_xmit, };