Blame view
net/openvswitch/vport-internal_dev.c
6.18 KB
c94229992 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
ccb1352e7 net: Add Open vSw... |
2 |
/* |
caf2ee14b openvswitch: Repl... |
3 |
* Copyright (c) 2007-2012 Nicira, Inc. |
ccb1352e7 net: Add Open vSw... |
4 |
*/ |
ccb1352e7 net: Add Open vSw... |
5 6 7 8 9 10 |
#include <linux/if_vlan.h> #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/skbuff.h> |
ccb1352e7 net: Add Open vSw... |
11 |
|
7fe99e2d4 openvswitch: Rese... |
12 13 |
#include <net/dst.h> #include <net/xfrm.h> |
5b9e7e160 openvswitch: intr... |
14 |
#include <net/rtnetlink.h> |
7fe99e2d4 openvswitch: Rese... |
15 |
|
ccb1352e7 net: Add Open vSw... |
16 17 18 19 20 21 22 |
#include "datapath.h" #include "vport-internal_dev.h" #include "vport-netdev.h" struct internal_dev { struct vport *vport; }; |
62b9c8d03 ovs: Turn vports ... |
23 |
static struct vport_ops ovs_internal_vport_ops; |
ccb1352e7 net: Add Open vSw... |
24 25 26 27 |
static struct internal_dev *internal_dev_priv(struct net_device *netdev) { return netdev_priv(netdev); } |
ccb1352e7 net: Add Open vSw... |
28 |
/* Called with rcu_read_lock_bh. */ |
eddf11e18 net: ovs: fix ret... |
29 30 |
static netdev_tx_t internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev) |
ccb1352e7 net: Add Open vSw... |
31 |
{ |
8c876639c openvswitch: Remo... |
32 33 34 |
int len, err; len = skb->len; |
ccb1352e7 net: Add Open vSw... |
35 |
rcu_read_lock(); |
8c876639c openvswitch: Remo... |
36 |
err = ovs_vport_receive(internal_dev_priv(netdev)->vport, skb, NULL); |
ccb1352e7 net: Add Open vSw... |
37 |
rcu_read_unlock(); |
8c876639c openvswitch: Remo... |
38 39 40 41 42 43 44 45 46 47 48 |
if (likely(!err)) { struct pcpu_sw_netstats *tstats = this_cpu_ptr(netdev->tstats); u64_stats_update_begin(&tstats->syncp); tstats->tx_bytes += len; tstats->tx_packets++; u64_stats_update_end(&tstats->syncp); } else { netdev->stats.tx_errors++; } |
eddf11e18 net: ovs: fix ret... |
49 |
return NETDEV_TX_OK; |
ccb1352e7 net: Add Open vSw... |
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
} static int internal_dev_open(struct net_device *netdev) { netif_start_queue(netdev); return 0; } static int internal_dev_stop(struct net_device *netdev) { netif_stop_queue(netdev); return 0; } static void internal_dev_getinfo(struct net_device *netdev, struct ethtool_drvinfo *info) { |
7826d43f2 ethtool: fix drvi... |
67 |
strlcpy(info->driver, "openvswitch", sizeof(info->driver)); |
ccb1352e7 net: Add Open vSw... |
68 69 70 71 72 73 |
} static const struct ethtool_ops internal_dev_ethtool_ops = { .get_drvinfo = internal_dev_getinfo, .get_link = ethtool_op_get_link, }; |
ccb1352e7 net: Add Open vSw... |
74 75 76 77 78 |
static void internal_dev_destructor(struct net_device *dev) { struct vport *vport = ovs_internal_dev_get_vport(dev); ovs_vport_free(vport); |
ccb1352e7 net: Add Open vSw... |
79 |
} |
bc1f44709 net: make ndo_get... |
80 |
static void |
1241365f1 openvswitch: Allo... |
81 82 |
internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) { |
1241365f1 openvswitch: Allo... |
83 84 85 86 87 |
memset(stats, 0, sizeof(*stats)); stats->rx_errors = dev->stats.rx_errors; stats->tx_errors = dev->stats.tx_errors; stats->tx_dropped = dev->stats.tx_dropped; stats->rx_dropped = dev->stats.rx_dropped; |
3569939a8 net: openvswitch:... |
88 |
dev_fetch_sw_netstats(stats, dev->tstats); |
1241365f1 openvswitch: Allo... |
89 |
} |
ccb1352e7 net: Add Open vSw... |
90 91 92 93 |
static const struct net_device_ops internal_dev_netdev_ops = { .ndo_open = internal_dev_open, .ndo_stop = internal_dev_stop, .ndo_start_xmit = internal_dev_xmit, |
9151991c0 openvswitch: Use ... |
94 |
.ndo_set_mac_address = eth_mac_addr, |
1241365f1 openvswitch: Allo... |
95 |
.ndo_get_stats64 = internal_get_stats, |
ccb1352e7 net: Add Open vSw... |
96 |
}; |
5b9e7e160 openvswitch: intr... |
97 98 99 |
static struct rtnl_link_ops internal_dev_link_ops __read_mostly = { .kind = "openvswitch", }; |
ccb1352e7 net: Add Open vSw... |
100 101 102 |
static void do_setup(struct net_device *netdev) { ether_setup(netdev); |
425df17ce openvswitch: Set ... |
103 |
netdev->max_mtu = ETH_MAX_MTU; |
ccb1352e7 net: Add Open vSw... |
104 105 106 |
netdev->netdev_ops = &internal_dev_netdev_ops; netdev->priv_flags &= ~IFF_TX_SKB_SHARING; |
3a927bc7c ovs: propagate pe... |
107 |
netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH | |
183dea581 openvswitch: do n... |
108 |
IFF_NO_QUEUE; |
cf124db56 net: Fix inconsis... |
109 |
netdev->needs_free_netdev = true; |
9464cc37f net: openvswitch:... |
110 |
netdev->priv_destructor = NULL; |
7ad24ea4b net: get rid of S... |
111 |
netdev->ethtool_ops = &internal_dev_ethtool_ops; |
5b9e7e160 openvswitch: intr... |
112 |
netdev->rtnl_link_ops = &internal_dev_link_ops; |
ccb1352e7 net: Add Open vSw... |
113 114 |
netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST | |
f6eec614d openvswitch: Enab... |
115 116 |
NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL; |
ccb1352e7 net: Add Open vSw... |
117 118 |
netdev->vlan_features = netdev->features; |
f6eec614d openvswitch: Enab... |
119 |
netdev->hw_enc_features = netdev->features; |
3145c037e openvswitch: add ... |
120 |
netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; |
ccb1352e7 net: Add Open vSw... |
121 |
netdev->hw_features = netdev->features & ~NETIF_F_LLTX; |
f6eec614d openvswitch: Enab... |
122 |
|
7ce5d2221 net: use eth_hw_a... |
123 |
eth_hw_addr_random(netdev); |
ccb1352e7 net: Add Open vSw... |
124 125 126 127 128 |
} static struct vport *internal_dev_create(const struct vport_parms *parms) { struct vport *vport; |
ccb1352e7 net: Add Open vSw... |
129 |
struct internal_dev *internal_dev; |
309b66970 net: openvswitch:... |
130 |
struct net_device *dev; |
ccb1352e7 net: Add Open vSw... |
131 |
int err; |
be4ace6e6 openvswitch: Move... |
132 |
vport = ovs_vport_alloc(0, &ovs_internal_vport_ops, parms); |
ccb1352e7 net: Add Open vSw... |
133 134 135 136 |
if (IS_ERR(vport)) { err = PTR_ERR(vport); goto error; } |
309b66970 net: openvswitch:... |
137 138 139 |
dev = alloc_netdev(sizeof(struct internal_dev), parms->name, NET_NAME_USER, do_setup); vport->dev = dev; |
be4ace6e6 openvswitch: Move... |
140 |
if (!vport->dev) { |
ccb1352e7 net: Add Open vSw... |
141 142 143 |
err = -ENOMEM; goto error_free_vport; } |
1241365f1 openvswitch: Allo... |
144 145 146 147 148 |
vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!vport->dev->tstats) { err = -ENOMEM; goto error_free_netdev; } |
ccb1352e7 net: Add Open vSw... |
149 |
|
be4ace6e6 openvswitch: Move... |
150 151 |
dev_net_set(vport->dev, ovs_dp_get_net(vport->dp)); internal_dev = internal_dev_priv(vport->dev); |
ccb1352e7 net: Add Open vSw... |
152 |
internal_dev->vport = vport; |
46df7b814 openvswitch: Add ... |
153 154 |
/* Restrict bridge port to current netns. */ if (vport->port_no == OVSP_LOCAL) |
be4ace6e6 openvswitch: Move... |
155 |
vport->dev->features |= NETIF_F_NETNS_LOCAL; |
46df7b814 openvswitch: Add ... |
156 |
|
8e4e1713e openvswitch: Simp... |
157 |
rtnl_lock(); |
be4ace6e6 openvswitch: Move... |
158 |
err = register_netdevice(vport->dev); |
9464cc37f net: openvswitch:... |
159 |
if (err) |
1241365f1 openvswitch: Allo... |
160 |
goto error_unlock; |
9464cc37f net: openvswitch:... |
161 |
vport->dev->priv_destructor = internal_dev_destructor; |
ccb1352e7 net: Add Open vSw... |
162 |
|
be4ace6e6 openvswitch: Move... |
163 |
dev_set_promiscuity(vport->dev, 1); |
8e4e1713e openvswitch: Simp... |
164 |
rtnl_unlock(); |
be4ace6e6 openvswitch: Move... |
165 |
netif_start_queue(vport->dev); |
ccb1352e7 net: Add Open vSw... |
166 167 |
return vport; |
1241365f1 openvswitch: Allo... |
168 |
error_unlock: |
8e4e1713e openvswitch: Simp... |
169 |
rtnl_unlock(); |
309b66970 net: openvswitch:... |
170 |
free_percpu(dev->tstats); |
1241365f1 openvswitch: Allo... |
171 |
error_free_netdev: |
309b66970 net: openvswitch:... |
172 |
free_netdev(dev); |
ccb1352e7 net: Add Open vSw... |
173 |
error_free_vport: |
9464cc37f net: openvswitch:... |
174 |
ovs_vport_free(vport); |
ccb1352e7 net: Add Open vSw... |
175 176 177 178 179 180 |
error: return ERR_PTR(err); } static void internal_dev_destroy(struct vport *vport) { |
be4ace6e6 openvswitch: Move... |
181 |
netif_stop_queue(vport->dev); |
8e4e1713e openvswitch: Simp... |
182 |
rtnl_lock(); |
be4ace6e6 openvswitch: Move... |
183 |
dev_set_promiscuity(vport->dev, -1); |
ccb1352e7 net: Add Open vSw... |
184 185 |
/* unregister_netdevice() waits for an RCU grace period. */ |
be4ace6e6 openvswitch: Move... |
186 |
unregister_netdevice(vport->dev); |
1241365f1 openvswitch: Allo... |
187 |
free_percpu(vport->dev->tstats); |
8e4e1713e openvswitch: Simp... |
188 |
rtnl_unlock(); |
ccb1352e7 net: Add Open vSw... |
189 |
} |
aec159247 openvswitch: Use ... |
190 |
static netdev_tx_t internal_dev_recv(struct sk_buff *skb) |
ccb1352e7 net: Add Open vSw... |
191 |
{ |
aec159247 openvswitch: Use ... |
192 |
struct net_device *netdev = skb->dev; |
ccb1352e7 net: Add Open vSw... |
193 |
|
e1f9c356d openvswitch: Drop... |
194 195 |
if (unlikely(!(netdev->flags & IFF_UP))) { kfree_skb(skb); |
8c876639c openvswitch: Remo... |
196 |
netdev->stats.rx_dropped++; |
aec159247 openvswitch: Use ... |
197 |
return NETDEV_TX_OK; |
e1f9c356d openvswitch: Drop... |
198 |
} |
7fe99e2d4 openvswitch: Rese... |
199 |
skb_dst_drop(skb); |
895b5c9f2 netfilter: drop b... |
200 |
nf_reset_ct(skb); |
7fe99e2d4 openvswitch: Rese... |
201 |
secpath_reset(skb); |
ccb1352e7 net: Add Open vSw... |
202 203 |
skb->pkt_type = PACKET_HOST; skb->protocol = eth_type_trans(skb, netdev); |
b34df5e80 openvswitch: make... |
204 |
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); |
e40b3727f net: openvswitch:... |
205 |
dev_sw_netstats_rx_add(netdev, skb->len); |
ccb1352e7 net: Add Open vSw... |
206 |
|
8c876639c openvswitch: Remo... |
207 |
netif_rx(skb); |
aec159247 openvswitch: Use ... |
208 |
return NETDEV_TX_OK; |
ccb1352e7 net: Add Open vSw... |
209 |
} |
62b9c8d03 ovs: Turn vports ... |
210 |
static struct vport_ops ovs_internal_vport_ops = { |
ccb1352e7 net: Add Open vSw... |
211 212 213 |
.type = OVS_VPORT_TYPE_INTERNAL, .create = internal_dev_create, .destroy = internal_dev_destroy, |
ccb1352e7 net: Add Open vSw... |
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
.send = internal_dev_recv, }; int ovs_is_internal_dev(const struct net_device *netdev) { return netdev->netdev_ops == &internal_dev_netdev_ops; } struct vport *ovs_internal_dev_get_vport(struct net_device *netdev) { if (!ovs_is_internal_dev(netdev)) return NULL; return internal_dev_priv(netdev)->vport; } |
5b9e7e160 openvswitch: intr... |
229 230 231 |
int ovs_internal_dev_rtnl_link_register(void) { |
62b9c8d03 ovs: Turn vports ... |
232 233 234 235 236 237 238 239 240 241 242 |
int err; err = rtnl_link_register(&internal_dev_link_ops); if (err < 0) return err; err = ovs_vport_ops_register(&ovs_internal_vport_ops); if (err < 0) rtnl_link_unregister(&internal_dev_link_ops); return err; |
5b9e7e160 openvswitch: intr... |
243 244 245 246 |
} void ovs_internal_dev_rtnl_link_unregister(void) { |
62b9c8d03 ovs: Turn vports ... |
247 |
ovs_vport_ops_unregister(&ovs_internal_vport_ops); |
5b9e7e160 openvswitch: intr... |
248 249 |
rtnl_link_unregister(&internal_dev_link_ops); } |