1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2007-2012 Nicira, Inc. |
4 | */ |
5 | |
6 | #include <linux/if_vlan.h> |
7 | #include <linux/kernel.h> |
8 | #include <linux/netdevice.h> |
9 | #include <linux/etherdevice.h> |
10 | #include <linux/ethtool.h> |
11 | #include <linux/skbuff.h> |
12 | |
13 | #include <net/dst.h> |
14 | #include <net/xfrm.h> |
15 | #include <net/rtnetlink.h> |
16 | |
17 | #include "datapath.h" |
18 | #include "vport-internal_dev.h" |
19 | #include "vport-netdev.h" |
20 | |
21 | struct internal_dev { |
22 | struct vport *vport; |
23 | }; |
24 | |
25 | static struct vport_ops ovs_internal_vport_ops; |
26 | |
27 | static struct internal_dev *internal_dev_priv(struct net_device *netdev) |
28 | { |
29 | return netdev_priv(dev: netdev); |
30 | } |
31 | |
32 | /* Called with rcu_read_lock_bh. */ |
33 | static netdev_tx_t |
34 | internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev) |
35 | { |
36 | int len, err; |
37 | |
38 | /* store len value because skb can be freed inside ovs_vport_receive() */ |
39 | len = skb->len; |
40 | |
41 | rcu_read_lock(); |
42 | err = ovs_vport_receive(internal_dev_priv(netdev)->vport, skb, NULL); |
43 | rcu_read_unlock(); |
44 | |
45 | if (likely(!err)) |
46 | dev_sw_netstats_tx_add(dev: netdev, packets: 1, len); |
47 | else |
48 | netdev->stats.tx_errors++; |
49 | |
50 | return NETDEV_TX_OK; |
51 | } |
52 | |
53 | static int internal_dev_open(struct net_device *netdev) |
54 | { |
55 | netif_start_queue(dev: netdev); |
56 | return 0; |
57 | } |
58 | |
59 | static int internal_dev_stop(struct net_device *netdev) |
60 | { |
61 | netif_stop_queue(dev: netdev); |
62 | return 0; |
63 | } |
64 | |
65 | static void internal_dev_getinfo(struct net_device *netdev, |
66 | struct ethtool_drvinfo *info) |
67 | { |
68 | strscpy(p: info->driver, q: "openvswitch" , size: sizeof(info->driver)); |
69 | } |
70 | |
71 | static const struct ethtool_ops internal_dev_ethtool_ops = { |
72 | .get_drvinfo = internal_dev_getinfo, |
73 | .get_link = ethtool_op_get_link, |
74 | }; |
75 | |
76 | static void internal_dev_destructor(struct net_device *dev) |
77 | { |
78 | struct vport *vport = ovs_internal_dev_get_vport(dev); |
79 | |
80 | ovs_vport_free(vport); |
81 | } |
82 | |
83 | static const struct net_device_ops internal_dev_netdev_ops = { |
84 | .ndo_open = internal_dev_open, |
85 | .ndo_stop = internal_dev_stop, |
86 | .ndo_start_xmit = internal_dev_xmit, |
87 | .ndo_set_mac_address = eth_mac_addr, |
88 | .ndo_get_stats64 = dev_get_tstats64, |
89 | }; |
90 | |
91 | static struct rtnl_link_ops internal_dev_link_ops __read_mostly = { |
92 | .kind = "openvswitch" , |
93 | }; |
94 | |
95 | static void do_setup(struct net_device *netdev) |
96 | { |
97 | ether_setup(dev: netdev); |
98 | |
99 | netdev->max_mtu = ETH_MAX_MTU; |
100 | |
101 | netdev->netdev_ops = &internal_dev_netdev_ops; |
102 | |
103 | netdev->priv_flags &= ~IFF_TX_SKB_SHARING; |
104 | netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH | |
105 | IFF_NO_QUEUE; |
106 | netdev->needs_free_netdev = true; |
107 | netdev->priv_destructor = NULL; |
108 | netdev->ethtool_ops = &internal_dev_ethtool_ops; |
109 | netdev->rtnl_link_ops = &internal_dev_link_ops; |
110 | |
111 | netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST | |
112 | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | |
113 | NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL; |
114 | |
115 | netdev->vlan_features = netdev->features; |
116 | netdev->hw_enc_features = netdev->features; |
117 | netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; |
118 | netdev->hw_features = netdev->features & ~NETIF_F_LLTX; |
119 | |
120 | eth_hw_addr_random(dev: netdev); |
121 | } |
122 | |
123 | static struct vport *internal_dev_create(const struct vport_parms *parms) |
124 | { |
125 | struct vport *vport; |
126 | struct internal_dev *internal_dev; |
127 | struct net_device *dev; |
128 | int err; |
129 | |
130 | vport = ovs_vport_alloc(priv_size: 0, &ovs_internal_vport_ops, parms); |
131 | if (IS_ERR(ptr: vport)) { |
132 | err = PTR_ERR(ptr: vport); |
133 | goto error; |
134 | } |
135 | |
136 | dev = alloc_netdev(sizeof(struct internal_dev), |
137 | parms->name, NET_NAME_USER, do_setup); |
138 | vport->dev = dev; |
139 | if (!vport->dev) { |
140 | err = -ENOMEM; |
141 | goto error_free_vport; |
142 | } |
143 | vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
144 | if (!vport->dev->tstats) { |
145 | err = -ENOMEM; |
146 | goto error_free_netdev; |
147 | } |
148 | |
149 | dev_net_set(dev: vport->dev, net: ovs_dp_get_net(dp: vport->dp)); |
150 | dev->ifindex = parms->desired_ifindex; |
151 | internal_dev = internal_dev_priv(netdev: vport->dev); |
152 | internal_dev->vport = vport; |
153 | |
154 | /* Restrict bridge port to current netns. */ |
155 | if (vport->port_no == OVSP_LOCAL) |
156 | vport->dev->features |= NETIF_F_NETNS_LOCAL; |
157 | |
158 | rtnl_lock(); |
159 | err = register_netdevice(dev: vport->dev); |
160 | if (err) |
161 | goto error_unlock; |
162 | vport->dev->priv_destructor = internal_dev_destructor; |
163 | |
164 | dev_set_promiscuity(dev: vport->dev, inc: 1); |
165 | rtnl_unlock(); |
166 | netif_start_queue(dev: vport->dev); |
167 | |
168 | return vport; |
169 | |
170 | error_unlock: |
171 | rtnl_unlock(); |
172 | free_percpu(pdata: dev->tstats); |
173 | error_free_netdev: |
174 | free_netdev(dev); |
175 | error_free_vport: |
176 | ovs_vport_free(vport); |
177 | error: |
178 | return ERR_PTR(error: err); |
179 | } |
180 | |
181 | static void internal_dev_destroy(struct vport *vport) |
182 | { |
183 | netif_stop_queue(dev: vport->dev); |
184 | rtnl_lock(); |
185 | dev_set_promiscuity(dev: vport->dev, inc: -1); |
186 | |
187 | /* unregister_netdevice() waits for an RCU grace period. */ |
188 | unregister_netdevice(dev: vport->dev); |
189 | free_percpu(pdata: vport->dev->tstats); |
190 | rtnl_unlock(); |
191 | } |
192 | |
193 | static int internal_dev_recv(struct sk_buff *skb) |
194 | { |
195 | struct net_device *netdev = skb->dev; |
196 | |
197 | if (unlikely(!(netdev->flags & IFF_UP))) { |
198 | kfree_skb(skb); |
199 | netdev->stats.rx_dropped++; |
200 | return NETDEV_TX_OK; |
201 | } |
202 | |
203 | skb_dst_drop(skb); |
204 | nf_reset_ct(skb); |
205 | secpath_reset(skb); |
206 | |
207 | skb->pkt_type = PACKET_HOST; |
208 | skb->protocol = eth_type_trans(skb, dev: netdev); |
209 | skb_postpull_rcsum(skb, start: eth_hdr(skb), ETH_HLEN); |
210 | dev_sw_netstats_rx_add(dev: netdev, len: skb->len); |
211 | |
212 | netif_rx(skb); |
213 | return NETDEV_TX_OK; |
214 | } |
215 | |
216 | static struct vport_ops ovs_internal_vport_ops = { |
217 | .type = OVS_VPORT_TYPE_INTERNAL, |
218 | .create = internal_dev_create, |
219 | .destroy = internal_dev_destroy, |
220 | .send = internal_dev_recv, |
221 | }; |
222 | |
223 | int ovs_is_internal_dev(const struct net_device *netdev) |
224 | { |
225 | return netdev->netdev_ops == &internal_dev_netdev_ops; |
226 | } |
227 | |
228 | struct vport *ovs_internal_dev_get_vport(struct net_device *netdev) |
229 | { |
230 | if (!ovs_is_internal_dev(netdev)) |
231 | return NULL; |
232 | |
233 | return internal_dev_priv(netdev)->vport; |
234 | } |
235 | |
236 | int ovs_internal_dev_rtnl_link_register(void) |
237 | { |
238 | int err; |
239 | |
240 | err = rtnl_link_register(ops: &internal_dev_link_ops); |
241 | if (err < 0) |
242 | return err; |
243 | |
244 | err = ovs_vport_ops_register(&ovs_internal_vport_ops); |
245 | if (err < 0) |
246 | rtnl_link_unregister(ops: &internal_dev_link_ops); |
247 | |
248 | return err; |
249 | } |
250 | |
251 | void ovs_internal_dev_rtnl_link_unregister(void) |
252 | { |
253 | ovs_vport_ops_unregister(ops: &ovs_internal_vport_ops); |
254 | rtnl_link_unregister(ops: &internal_dev_link_ops); |
255 | } |
256 | |