Skip to content

Commit 3a927bc

Browse files
Paolo Abenidavem330
authored andcommitted
ovs: propagate per dp max headroom to all vports
This patch implements bookkeeping support to compute the maximum headroom for all the devices in each datapath. When said value changes, the underlying devs are notified via the ndo_set_rx_headroom method. This also increases the internal vports xmit performance. Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 45493d4 commit 3a927bc

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

net/openvswitch/datapath.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,29 @@ static struct vport *lookup_vport(struct net *net,
19081908
return ERR_PTR(-EINVAL);
19091909
}
19101910

1911+
/* Called with ovs_mutex */
1912+
static void update_headroom(struct datapath *dp)
1913+
{
1914+
unsigned dev_headroom, max_headroom = 0;
1915+
struct net_device *dev;
1916+
struct vport *vport;
1917+
int i;
1918+
1919+
for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
1920+
hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node) {
1921+
dev = vport->dev;
1922+
dev_headroom = netdev_get_fwd_headroom(dev);
1923+
if (dev_headroom > max_headroom)
1924+
max_headroom = dev_headroom;
1925+
}
1926+
}
1927+
1928+
dp->max_headroom = max_headroom;
1929+
for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++)
1930+
hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node)
1931+
netdev_set_rx_headroom(vport->dev, max_headroom);
1932+
}
1933+
19111934
static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
19121935
{
19131936
struct nlattr **a = info->attrs;
@@ -1973,6 +1996,12 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
19731996

19741997
err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
19751998
info->snd_seq, 0, OVS_VPORT_CMD_NEW);
1999+
2000+
if (netdev_get_fwd_headroom(vport->dev) > dp->max_headroom)
2001+
update_headroom(dp);
2002+
else
2003+
netdev_set_rx_headroom(vport->dev, dp->max_headroom);
2004+
19762005
BUG_ON(err < 0);
19772006
ovs_unlock();
19782007

@@ -2039,8 +2068,10 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
20392068

20402069
static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
20412070
{
2071+
bool must_update_headroom = false;
20422072
struct nlattr **a = info->attrs;
20432073
struct sk_buff *reply;
2074+
struct datapath *dp;
20442075
struct vport *vport;
20452076
int err;
20462077

@@ -2062,7 +2093,16 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
20622093
err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
20632094
info->snd_seq, 0, OVS_VPORT_CMD_DEL);
20642095
BUG_ON(err < 0);
2096+
2097+
/* the vport deletion may trigger dp headroom update */
2098+
dp = vport->dp;
2099+
if (netdev_get_fwd_headroom(vport->dev) == dp->max_headroom)
2100+
must_update_headroom = true;
2101+
netdev_reset_rx_headroom(vport->dev);
20652102
ovs_dp_detach_port(vport);
2103+
2104+
if (must_update_headroom)
2105+
update_headroom(dp);
20662106
ovs_unlock();
20672107

20682108
ovs_notify(&dp_vport_genl_family, reply, info);

net/openvswitch/datapath.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ struct dp_stats_percpu {
6868
* ovs_mutex and RCU.
6969
* @stats_percpu: Per-CPU datapath statistics.
7070
* @net: Reference to net namespace.
71+
* @max_headroom: the maximum headroom of all vports in this datapath; it will
72+
* be used by all the internal vports in this dp.
7173
*
7274
* Context: See the comment on locking at the top of datapath.c for additional
7375
* locking information.
@@ -89,6 +91,8 @@ struct datapath {
8991
possible_net_t net;
9092

9193
u32 user_features;
94+
95+
u32 max_headroom;
9296
};
9397

9498
/**

net/openvswitch/vport-internal_dev.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,19 @@ internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
138138
return stats;
139139
}
140140

141+
void internal_set_rx_headroom(struct net_device *dev, int new_hr)
142+
{
143+
dev->needed_headroom = new_hr;
144+
}
145+
141146
static const struct net_device_ops internal_dev_netdev_ops = {
142147
.ndo_open = internal_dev_open,
143148
.ndo_stop = internal_dev_stop,
144149
.ndo_start_xmit = internal_dev_xmit,
145150
.ndo_set_mac_address = eth_mac_addr,
146151
.ndo_change_mtu = internal_dev_change_mtu,
147152
.ndo_get_stats64 = internal_get_stats,
153+
.ndo_set_rx_headroom = internal_set_rx_headroom,
148154
};
149155

150156
static struct rtnl_link_ops internal_dev_link_ops __read_mostly = {
@@ -158,7 +164,8 @@ static void do_setup(struct net_device *netdev)
158164
netdev->netdev_ops = &internal_dev_netdev_ops;
159165

160166
netdev->priv_flags &= ~IFF_TX_SKB_SHARING;
161-
netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH;
167+
netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH |
168+
IFF_PHONY_HEADROOM;
162169
netdev->destructor = internal_dev_destructor;
163170
netdev->ethtool_ops = &internal_dev_ethtool_ops;
164171
netdev->rtnl_link_ops = &internal_dev_link_ops;
@@ -199,6 +206,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
199206
err = -ENOMEM;
200207
goto error_free_netdev;
201208
}
209+
vport->dev->needed_headroom = vport->dp->max_headroom;
202210

203211
dev_net_set(vport->dev, ovs_dp_get_net(vport->dp));
204212
internal_dev = internal_dev_priv(vport->dev);

0 commit comments

Comments
 (0)