Skip to content

Commit bcbf1be

Browse files
committed
Merge branch 'udp_tunnel-convert-Intel-drivers-with-shared-tables'
Jakub Kicinski says: ==================== udp_tunnel: convert Intel drivers with shared tables This set converts Intel drivers which have the ability to spawn multiple netdevs, but have only one UDP tunnel port table. Appropriate support is added to the core infra in patch 1, followed by netdevsim support and a selftest. The table sharing works by core attaching the same table structure to all devices sharing the table. This means the reference count has to accommodate potentially large values. Once core is ready i40e and ice are converted. These are complex drivers, but we got a tested-by from Aaron, so we should be good :) Compared to v1 I've made sure the selftest is executable. Other than that patches 8 and 9 are actually from the Mellanox conversion series were kept out to avoid Mellanox vs Intel conflicts. Last patch is new, some docs to let users knows ethtool can now display UDP tunnel info. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 8744c0a + 33a1aaf commit bcbf1be

File tree

15 files changed

+531
-451
lines changed

15 files changed

+531
-451
lines changed

Documentation/networking/vxlan.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,31 @@ forwarding table using the new bridge command.
5858
3. Show forwarding table::
5959

6060
# bridge fdb show dev vxlan0
61+
62+
The following NIC features may indicate support for UDP tunnel-related
63+
offloads (most commonly VXLAN features, but support for a particular
64+
encapsulation protocol is NIC specific):
65+
66+
- `tx-udp_tnl-segmentation`
67+
- `tx-udp_tnl-csum-segmentation`
68+
ability to perform TCP segmentation offload of UDP encapsulated frames
69+
70+
- `rx-udp_tunnel-port-offload`
71+
receive side parsing of UDP encapsulated frames which allows NICs to
72+
perform protocol-aware offloads, like checksum validation offload of
73+
inner frames (only needed by NICs without protocol-agnostic offloads)
74+
75+
For devices supporting `rx-udp_tunnel-port-offload` the list of currently
76+
offloaded ports can be interrogated with `ethtool`::
77+
78+
$ ethtool --show-tunnels eth0
79+
Tunnel information for eth0:
80+
UDP port table 0:
81+
Size: 4
82+
Types: vxlan
83+
No entries
84+
UDP port table 1:
85+
Size: 4
86+
Types: geneve, vxlan-gpe
87+
Entries (1):
88+
port 1230, vxlan-gpe

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <net/pkt_cls.h>
3636
#include <net/tc_act/tc_gact.h>
3737
#include <net/tc_act/tc_mirred.h>
38+
#include <net/udp_tunnel.h>
3839
#include <net/xdp_sock.h>
3940
#include "i40e_type.h"
4041
#include "i40e_prototype.h"
@@ -133,7 +134,6 @@ enum i40e_state_t {
133134
__I40E_PORT_SUSPENDED,
134135
__I40E_VF_DISABLE,
135136
__I40E_MACVLAN_SYNC_PENDING,
136-
__I40E_UDP_FILTER_SYNC_PENDING,
137137
__I40E_TEMP_LINK_POLLING,
138138
__I40E_CLIENT_SERVICE_REQUESTED,
139139
__I40E_CLIENT_L2_CHANGE,
@@ -478,8 +478,8 @@ struct i40e_pf {
478478
struct list_head l3_flex_pit_list;
479479
struct list_head l4_flex_pit_list;
480480

481-
struct i40e_udp_port_config udp_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
482-
u16 pending_udp_bitmap;
481+
struct udp_tunnel_nic_shared udp_tunnel_shared;
482+
struct udp_tunnel_nic_info udp_tunnel_nic;
483483

484484
struct hlist_head cloud_filter_list;
485485
u16 num_cloud_filters;

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 48 additions & 216 deletions
Original file line numberDiff line numberDiff line change
@@ -10386,106 +10386,6 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
1038610386
i40e_flush(hw);
1038710387
}
1038810388

10389-
static const char *i40e_tunnel_name(u8 type)
10390-
{
10391-
switch (type) {
10392-
case UDP_TUNNEL_TYPE_VXLAN:
10393-
return "vxlan";
10394-
case UDP_TUNNEL_TYPE_GENEVE:
10395-
return "geneve";
10396-
default:
10397-
return "unknown";
10398-
}
10399-
}
10400-
10401-
/**
10402-
* i40e_sync_udp_filters - Trigger a sync event for existing UDP filters
10403-
* @pf: board private structure
10404-
**/
10405-
static void i40e_sync_udp_filters(struct i40e_pf *pf)
10406-
{
10407-
int i;
10408-
10409-
/* loop through and set pending bit for all active UDP filters */
10410-
for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
10411-
if (pf->udp_ports[i].port)
10412-
pf->pending_udp_bitmap |= BIT_ULL(i);
10413-
}
10414-
10415-
set_bit(__I40E_UDP_FILTER_SYNC_PENDING, pf->state);
10416-
}
10417-
10418-
/**
10419-
* i40e_sync_udp_filters_subtask - Sync the VSI filter list with HW
10420-
* @pf: board private structure
10421-
**/
10422-
static void i40e_sync_udp_filters_subtask(struct i40e_pf *pf)
10423-
{
10424-
struct i40e_hw *hw = &pf->hw;
10425-
u8 filter_index, type;
10426-
u16 port;
10427-
int i;
10428-
10429-
if (!test_and_clear_bit(__I40E_UDP_FILTER_SYNC_PENDING, pf->state))
10430-
return;
10431-
10432-
/* acquire RTNL to maintain state of flags and port requests */
10433-
rtnl_lock();
10434-
10435-
for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
10436-
if (pf->pending_udp_bitmap & BIT_ULL(i)) {
10437-
struct i40e_udp_port_config *udp_port;
10438-
i40e_status ret = 0;
10439-
10440-
udp_port = &pf->udp_ports[i];
10441-
pf->pending_udp_bitmap &= ~BIT_ULL(i);
10442-
10443-
port = READ_ONCE(udp_port->port);
10444-
type = READ_ONCE(udp_port->type);
10445-
filter_index = READ_ONCE(udp_port->filter_index);
10446-
10447-
/* release RTNL while we wait on AQ command */
10448-
rtnl_unlock();
10449-
10450-
if (port)
10451-
ret = i40e_aq_add_udp_tunnel(hw, port,
10452-
type,
10453-
&filter_index,
10454-
NULL);
10455-
else if (filter_index != I40E_UDP_PORT_INDEX_UNUSED)
10456-
ret = i40e_aq_del_udp_tunnel(hw, filter_index,
10457-
NULL);
10458-
10459-
/* reacquire RTNL so we can update filter_index */
10460-
rtnl_lock();
10461-
10462-
if (ret) {
10463-
dev_info(&pf->pdev->dev,
10464-
"%s %s port %d, index %d failed, err %s aq_err %s\n",
10465-
i40e_tunnel_name(type),
10466-
port ? "add" : "delete",
10467-
port,
10468-
filter_index,
10469-
i40e_stat_str(&pf->hw, ret),
10470-
i40e_aq_str(&pf->hw,
10471-
pf->hw.aq.asq_last_status));
10472-
if (port) {
10473-
/* failed to add, just reset port,
10474-
* drop pending bit for any deletion
10475-
*/
10476-
udp_port->port = 0;
10477-
pf->pending_udp_bitmap &= ~BIT_ULL(i);
10478-
}
10479-
} else if (port) {
10480-
/* record filter index on success */
10481-
udp_port->filter_index = filter_index;
10482-
}
10483-
}
10484-
}
10485-
10486-
rtnl_unlock();
10487-
}
10488-
1048910389
/**
1049010390
* i40e_service_task - Run the driver's async subtasks
1049110391
* @work: pointer to work_struct containing our data
@@ -10525,7 +10425,6 @@ static void i40e_service_task(struct work_struct *work)
1052510425
pf->vsi[pf->lan_vsi]);
1052610426
}
1052710427
i40e_sync_filters_subtask(pf);
10528-
i40e_sync_udp_filters_subtask(pf);
1052910428
} else {
1053010429
i40e_reset_subtask(pf);
1053110430
}
@@ -12225,131 +12124,48 @@ static int i40e_set_features(struct net_device *netdev,
1222512124
return 0;
1222612125
}
1222712126

12228-
/**
12229-
* i40e_get_udp_port_idx - Lookup a possibly offloaded for Rx UDP port
12230-
* @pf: board private structure
12231-
* @port: The UDP port to look up
12232-
*
12233-
* Returns the index number or I40E_MAX_PF_UDP_OFFLOAD_PORTS if port not found
12234-
**/
12235-
static u8 i40e_get_udp_port_idx(struct i40e_pf *pf, u16 port)
12236-
{
12237-
u8 i;
12238-
12239-
for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
12240-
/* Do not report ports with pending deletions as
12241-
* being available.
12242-
*/
12243-
if (!port && (pf->pending_udp_bitmap & BIT_ULL(i)))
12244-
continue;
12245-
if (pf->udp_ports[i].port == port)
12246-
return i;
12247-
}
12248-
12249-
return i;
12250-
}
12251-
12252-
/**
12253-
* i40e_udp_tunnel_add - Get notifications about UDP tunnel ports that come up
12254-
* @netdev: This physical port's netdev
12255-
* @ti: Tunnel endpoint information
12256-
**/
12257-
static void i40e_udp_tunnel_add(struct net_device *netdev,
12258-
struct udp_tunnel_info *ti)
12127+
static int i40e_udp_tunnel_set_port(struct net_device *netdev,
12128+
unsigned int table, unsigned int idx,
12129+
struct udp_tunnel_info *ti)
1225912130
{
1226012131
struct i40e_netdev_priv *np = netdev_priv(netdev);
12261-
struct i40e_vsi *vsi = np->vsi;
12262-
struct i40e_pf *pf = vsi->back;
12263-
u16 port = ntohs(ti->port);
12264-
u8 next_idx;
12265-
u8 idx;
12266-
12267-
idx = i40e_get_udp_port_idx(pf, port);
12268-
12269-
/* Check if port already exists */
12270-
if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
12271-
netdev_info(netdev, "port %d already offloaded\n", port);
12272-
return;
12273-
}
12274-
12275-
/* Now check if there is space to add the new port */
12276-
next_idx = i40e_get_udp_port_idx(pf, 0);
12132+
struct i40e_hw *hw = &np->vsi->back->hw;
12133+
u8 type, filter_index;
12134+
i40e_status ret;
1227712135

12278-
if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
12279-
netdev_info(netdev, "maximum number of offloaded UDP ports reached, not adding port %d\n",
12280-
port);
12281-
return;
12282-
}
12136+
type = ti->type == UDP_TUNNEL_TYPE_VXLAN ? I40E_AQC_TUNNEL_TYPE_VXLAN :
12137+
I40E_AQC_TUNNEL_TYPE_NGE;
1228312138

12284-
switch (ti->type) {
12285-
case UDP_TUNNEL_TYPE_VXLAN:
12286-
pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_VXLAN;
12287-
break;
12288-
case UDP_TUNNEL_TYPE_GENEVE:
12289-
if (!(pf->hw_features & I40E_HW_GENEVE_OFFLOAD_CAPABLE))
12290-
return;
12291-
pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_NGE;
12292-
break;
12293-
default:
12294-
return;
12139+
ret = i40e_aq_add_udp_tunnel(hw, ntohs(ti->port), type, &filter_index,
12140+
NULL);
12141+
if (ret) {
12142+
netdev_info(netdev, "add UDP port failed, err %s aq_err %s\n",
12143+
i40e_stat_str(hw, ret),
12144+
i40e_aq_str(hw, hw->aq.asq_last_status));
12145+
return -EIO;
1229512146
}
1229612147

12297-
/* New port: add it and mark its index in the bitmap */
12298-
pf->udp_ports[next_idx].port = port;
12299-
pf->udp_ports[next_idx].filter_index = I40E_UDP_PORT_INDEX_UNUSED;
12300-
pf->pending_udp_bitmap |= BIT_ULL(next_idx);
12301-
set_bit(__I40E_UDP_FILTER_SYNC_PENDING, pf->state);
12148+
udp_tunnel_nic_set_port_priv(netdev, table, idx, filter_index);
12149+
return 0;
1230212150
}
1230312151

12304-
/**
12305-
* i40e_udp_tunnel_del - Get notifications about UDP tunnel ports that go away
12306-
* @netdev: This physical port's netdev
12307-
* @ti: Tunnel endpoint information
12308-
**/
12309-
static void i40e_udp_tunnel_del(struct net_device *netdev,
12310-
struct udp_tunnel_info *ti)
12152+
static int i40e_udp_tunnel_unset_port(struct net_device *netdev,
12153+
unsigned int table, unsigned int idx,
12154+
struct udp_tunnel_info *ti)
1231112155
{
1231212156
struct i40e_netdev_priv *np = netdev_priv(netdev);
12313-
struct i40e_vsi *vsi = np->vsi;
12314-
struct i40e_pf *pf = vsi->back;
12315-
u16 port = ntohs(ti->port);
12316-
u8 idx;
12317-
12318-
idx = i40e_get_udp_port_idx(pf, port);
12319-
12320-
/* Check if port already exists */
12321-
if (idx >= I40E_MAX_PF_UDP_OFFLOAD_PORTS)
12322-
goto not_found;
12157+
struct i40e_hw *hw = &np->vsi->back->hw;
12158+
i40e_status ret;
1232312159

12324-
switch (ti->type) {
12325-
case UDP_TUNNEL_TYPE_VXLAN:
12326-
if (pf->udp_ports[idx].type != I40E_AQC_TUNNEL_TYPE_VXLAN)
12327-
goto not_found;
12328-
break;
12329-
case UDP_TUNNEL_TYPE_GENEVE:
12330-
if (pf->udp_ports[idx].type != I40E_AQC_TUNNEL_TYPE_NGE)
12331-
goto not_found;
12332-
break;
12333-
default:
12334-
goto not_found;
12160+
ret = i40e_aq_del_udp_tunnel(hw, ti->hw_priv, NULL);
12161+
if (ret) {
12162+
netdev_info(netdev, "delete UDP port failed, err %s aq_err %s\n",
12163+
i40e_stat_str(hw, ret),
12164+
i40e_aq_str(hw, hw->aq.asq_last_status));
12165+
return -EIO;
1233512166
}
1233612167

12337-
/* if port exists, set it to 0 (mark for deletion)
12338-
* and make it pending
12339-
*/
12340-
pf->udp_ports[idx].port = 0;
12341-
12342-
/* Toggle pending bit instead of setting it. This way if we are
12343-
* deleting a port that has yet to be added we just clear the pending
12344-
* bit and don't have to worry about it.
12345-
*/
12346-
pf->pending_udp_bitmap ^= BIT_ULL(idx);
12347-
set_bit(__I40E_UDP_FILTER_SYNC_PENDING, pf->state);
12348-
12349-
return;
12350-
not_found:
12351-
netdev_warn(netdev, "UDP port %d was not found, not deleting\n",
12352-
port);
12168+
return 0;
1235312169
}
1235412170

1235512171
static int i40e_get_phys_port_id(struct net_device *netdev,
@@ -12955,8 +12771,8 @@ static const struct net_device_ops i40e_netdev_ops = {
1295512771
.ndo_set_vf_link_state = i40e_ndo_set_vf_link_state,
1295612772
.ndo_set_vf_spoofchk = i40e_ndo_set_vf_spoofchk,
1295712773
.ndo_set_vf_trust = i40e_ndo_set_vf_trust,
12958-
.ndo_udp_tunnel_add = i40e_udp_tunnel_add,
12959-
.ndo_udp_tunnel_del = i40e_udp_tunnel_del,
12774+
.ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
12775+
.ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
1296012776
.ndo_get_phys_port_id = i40e_get_phys_port_id,
1296112777
.ndo_fdb_add = i40e_ndo_fdb_add,
1296212778
.ndo_features_check = i40e_features_check,
@@ -13020,6 +12836,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
1302012836
if (!(pf->hw_features & I40E_HW_OUTER_UDP_CSUM_CAPABLE))
1302112837
netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
1302212838

12839+
netdev->udp_tunnel_nic_info = &pf->udp_tunnel_nic;
12840+
1302312841
netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
1302412842

1302512843
netdev->hw_enc_features |= hw_enc_features;
@@ -14420,7 +14238,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
1442014238
i40e_ptp_init(pf);
1442114239

1442214240
/* repopulate tunnel port filters */
14423-
i40e_sync_udp_filters(pf);
14241+
udp_tunnel_nic_reset_ntf(pf->vsi[pf->lan_vsi]->netdev);
1442414242

1442514243
return ret;
1442614244
}
@@ -15149,6 +14967,14 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1514914967
if (err)
1515014968
goto err_switch_setup;
1515114969

14970+
pf->udp_tunnel_nic.set_port = i40e_udp_tunnel_set_port;
14971+
pf->udp_tunnel_nic.unset_port = i40e_udp_tunnel_unset_port;
14972+
pf->udp_tunnel_nic.flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP;
14973+
pf->udp_tunnel_nic.shared = &pf->udp_tunnel_shared;
14974+
pf->udp_tunnel_nic.tables[0].n_entries = I40E_MAX_PF_UDP_OFFLOAD_PORTS;
14975+
pf->udp_tunnel_nic.tables[0].tunnel_types = UDP_TUNNEL_TYPE_VXLAN |
14976+
UDP_TUNNEL_TYPE_GENEVE;
14977+
1515214978
/* The number of VSIs reported by the FW is the minimum guaranteed
1515314979
* to us; HW supports far more and we share the remaining pool with
1515414980
* the other PFs. We allocate space for more than the guarantee with
@@ -15158,6 +14984,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1515814984
pf->num_alloc_vsi = I40E_MIN_VSI_ALLOC;
1515914985
else
1516014986
pf->num_alloc_vsi = pf->hw.func_caps.num_vsis;
14987+
if (pf->num_alloc_vsi > UDP_TUNNEL_NIC_MAX_SHARING_DEVICES) {
14988+
dev_warn(&pf->pdev->dev,
14989+
"limiting the VSI count due to UDP tunnel limitation %d > %d\n",
14990+
pf->num_alloc_vsi, UDP_TUNNEL_NIC_MAX_SHARING_DEVICES);
14991+
pf->num_alloc_vsi = UDP_TUNNEL_NIC_MAX_SHARING_DEVICES;
14992+
}
1516114993

1516214994
/* Set up the *vsi struct and our local tracking of the MAIN PF vsi. */
1516314995
pf->vsi = kcalloc(pf->num_alloc_vsi, sizeof(struct i40e_vsi *),

0 commit comments

Comments
 (0)