Skip to content

Commit b27d6a9

Browse files
jahurleydavem330
authored andcommitted
nfp: compile flower vxlan tunnel set actions
Compile set tunnel actions for tc flower. Only support VXLAN and ensure a tunnel destination port of 4789 is used. Signed-off-by: John Hurley <[email protected]> Signed-off-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 611aec1 commit b27d6a9

File tree

2 files changed

+179
-21
lines changed

2 files changed

+179
-21
lines changed

drivers/net/ethernet/netronome/nfp/flower/action.c

Lines changed: 152 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <net/tc_act/tc_gact.h>
3838
#include <net/tc_act/tc_mirred.h>
3939
#include <net/tc_act/tc_vlan.h>
40+
#include <net/tc_act/tc_tunnel_key.h>
4041

4142
#include "cmsg.h"
4243
#include "main.h"
@@ -80,14 +81,27 @@ nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan,
8081
push_vlan->vlan_tci = cpu_to_be16(tmp_push_vlan_tci);
8182
}
8283

84+
static bool nfp_fl_netdev_is_tunnel_type(struct net_device *out_dev,
85+
enum nfp_flower_tun_type tun_type)
86+
{
87+
if (!out_dev->rtnl_link_ops)
88+
return false;
89+
90+
if (!strcmp(out_dev->rtnl_link_ops->kind, "vxlan"))
91+
return tun_type == NFP_FL_TUNNEL_VXLAN;
92+
93+
return false;
94+
}
95+
8396
static int
8497
nfp_fl_output(struct nfp_fl_output *output, const struct tc_action *action,
8598
struct nfp_fl_payload *nfp_flow, bool last,
86-
struct net_device *in_dev)
99+
struct net_device *in_dev, enum nfp_flower_tun_type tun_type,
100+
int *tun_out_cnt)
87101
{
88102
size_t act_size = sizeof(struct nfp_fl_output);
103+
u16 tmp_output_op, tmp_flags;
89104
struct net_device *out_dev;
90-
u16 tmp_output_op;
91105
int ifindex;
92106

93107
/* Set action opcode to output action. */
@@ -97,34 +111,126 @@ nfp_fl_output(struct nfp_fl_output *output, const struct tc_action *action,
97111

98112
output->a_op = cpu_to_be16(tmp_output_op);
99113

100-
/* Set action output parameters. */
101-
output->flags = cpu_to_be16(last ? NFP_FL_OUT_FLAGS_LAST : 0);
102-
103114
ifindex = tcf_mirred_ifindex(action);
104115
out_dev = __dev_get_by_index(dev_net(in_dev), ifindex);
105116
if (!out_dev)
106117
return -EOPNOTSUPP;
107118

108-
/* Only offload egress ports are on the same device as the ingress
109-
* port.
119+
tmp_flags = last ? NFP_FL_OUT_FLAGS_LAST : 0;
120+
121+
if (tun_type) {
122+
/* Verify the egress netdev matches the tunnel type. */
123+
if (!nfp_fl_netdev_is_tunnel_type(out_dev, tun_type))
124+
return -EOPNOTSUPP;
125+
126+
if (*tun_out_cnt)
127+
return -EOPNOTSUPP;
128+
(*tun_out_cnt)++;
129+
130+
output->flags = cpu_to_be16(tmp_flags |
131+
NFP_FL_OUT_FLAGS_USE_TUN);
132+
output->port = cpu_to_be32(NFP_FL_PORT_TYPE_TUN | tun_type);
133+
} else {
134+
/* Set action output parameters. */
135+
output->flags = cpu_to_be16(tmp_flags);
136+
137+
/* Only offload if egress ports are on the same device as the
138+
* ingress port.
139+
*/
140+
if (!switchdev_port_same_parent_id(in_dev, out_dev))
141+
return -EOPNOTSUPP;
142+
143+
output->port = cpu_to_be32(nfp_repr_get_port_id(out_dev));
144+
if (!output->port)
145+
return -EOPNOTSUPP;
146+
}
147+
nfp_flow->meta.shortcut = output->port;
148+
149+
return 0;
150+
}
151+
152+
static bool nfp_fl_supported_tun_port(const struct tc_action *action)
153+
{
154+
struct ip_tunnel_info *tun = tcf_tunnel_info(action);
155+
156+
return tun->key.tp_dst == htons(NFP_FL_VXLAN_PORT);
157+
}
158+
159+
static struct nfp_fl_pre_tunnel *nfp_fl_pre_tunnel(char *act_data, int act_len)
160+
{
161+
size_t act_size = sizeof(struct nfp_fl_pre_tunnel);
162+
struct nfp_fl_pre_tunnel *pre_tun_act;
163+
u16 tmp_pre_tun_op;
164+
165+
/* Pre_tunnel action must be first on action list.
166+
* If other actions already exist they need pushed forward.
110167
*/
111-
if (!switchdev_port_same_parent_id(in_dev, out_dev))
112-
return -EOPNOTSUPP;
168+
if (act_len)
169+
memmove(act_data + act_size, act_data, act_len);
170+
171+
pre_tun_act = (struct nfp_fl_pre_tunnel *)act_data;
172+
173+
memset(pre_tun_act, 0, act_size);
174+
175+
tmp_pre_tun_op =
176+
FIELD_PREP(NFP_FL_ACT_LEN_LW, act_size >> NFP_FL_LW_SIZ) |
177+
FIELD_PREP(NFP_FL_ACT_JMP_ID, NFP_FL_ACTION_OPCODE_PRE_TUNNEL);
178+
179+
pre_tun_act->a_op = cpu_to_be16(tmp_pre_tun_op);
113180

114-
output->port = cpu_to_be32(nfp_repr_get_port_id(out_dev));
115-
if (!output->port)
181+
return pre_tun_act;
182+
}
183+
184+
static int
185+
nfp_fl_set_vxlan(struct nfp_fl_set_vxlan *set_vxlan,
186+
const struct tc_action *action,
187+
struct nfp_fl_pre_tunnel *pre_tun)
188+
{
189+
struct ip_tunnel_info *vxlan = tcf_tunnel_info(action);
190+
size_t act_size = sizeof(struct nfp_fl_set_vxlan);
191+
u32 tmp_set_vxlan_type_index = 0;
192+
u16 tmp_set_vxlan_op;
193+
/* Currently support one pre-tunnel so index is always 0. */
194+
int pretun_idx = 0;
195+
196+
if (vxlan->options_len) {
197+
/* Do not support options e.g. vxlan gpe. */
116198
return -EOPNOTSUPP;
199+
}
117200

118-
nfp_flow->meta.shortcut = output->port;
201+
tmp_set_vxlan_op =
202+
FIELD_PREP(NFP_FL_ACT_LEN_LW, act_size >> NFP_FL_LW_SIZ) |
203+
FIELD_PREP(NFP_FL_ACT_JMP_ID,
204+
NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL);
205+
206+
set_vxlan->a_op = cpu_to_be16(tmp_set_vxlan_op);
207+
208+
/* Set tunnel type and pre-tunnel index. */
209+
tmp_set_vxlan_type_index |=
210+
FIELD_PREP(NFP_FL_IPV4_TUNNEL_TYPE, NFP_FL_TUNNEL_VXLAN) |
211+
FIELD_PREP(NFP_FL_IPV4_PRE_TUN_INDEX, pretun_idx);
212+
213+
set_vxlan->tun_type_index = cpu_to_be32(tmp_set_vxlan_type_index);
214+
215+
set_vxlan->tun_id = vxlan->key.tun_id;
216+
set_vxlan->tun_flags = vxlan->key.tun_flags;
217+
set_vxlan->ipv4_ttl = vxlan->key.ttl;
218+
set_vxlan->ipv4_tos = vxlan->key.tos;
219+
220+
/* Complete pre_tunnel action. */
221+
pre_tun->ipv4_dst = vxlan->key.u.ipv4.dst;
119222

120223
return 0;
121224
}
122225

123226
static int
124227
nfp_flower_loop_action(const struct tc_action *a,
125228
struct nfp_fl_payload *nfp_fl, int *a_len,
126-
struct net_device *netdev)
229+
struct net_device *netdev,
230+
enum nfp_flower_tun_type *tun_type, int *tun_out_cnt)
127231
{
232+
struct nfp_fl_pre_tunnel *pre_tun;
233+
struct nfp_fl_set_vxlan *s_vxl;
128234
struct nfp_fl_push_vlan *psh_v;
129235
struct nfp_fl_pop_vlan *pop_v;
130236
struct nfp_fl_output *output;
@@ -137,7 +243,8 @@ nfp_flower_loop_action(const struct tc_action *a,
137243
return -EOPNOTSUPP;
138244

139245
output = (struct nfp_fl_output *)&nfp_fl->action_data[*a_len];
140-
err = nfp_fl_output(output, a, nfp_fl, true, netdev);
246+
err = nfp_fl_output(output, a, nfp_fl, true, netdev, *tun_type,
247+
tun_out_cnt);
141248
if (err)
142249
return err;
143250

@@ -147,7 +254,8 @@ nfp_flower_loop_action(const struct tc_action *a,
147254
return -EOPNOTSUPP;
148255

149256
output = (struct nfp_fl_output *)&nfp_fl->action_data[*a_len];
150-
err = nfp_fl_output(output, a, nfp_fl, false, netdev);
257+
err = nfp_fl_output(output, a, nfp_fl, false, netdev, *tun_type,
258+
tun_out_cnt);
151259
if (err)
152260
return err;
153261

@@ -170,6 +278,29 @@ nfp_flower_loop_action(const struct tc_action *a,
170278

171279
nfp_fl_push_vlan(psh_v, a);
172280
*a_len += sizeof(struct nfp_fl_push_vlan);
281+
} else if (is_tcf_tunnel_set(a) && nfp_fl_supported_tun_port(a)) {
282+
/* Pre-tunnel action is required for tunnel encap.
283+
* This checks for next hop entries on NFP.
284+
* If none, the packet falls back before applying other actions.
285+
*/
286+
if (*a_len + sizeof(struct nfp_fl_pre_tunnel) +
287+
sizeof(struct nfp_fl_set_vxlan) > NFP_FL_MAX_A_SIZ)
288+
return -EOPNOTSUPP;
289+
290+
*tun_type = NFP_FL_TUNNEL_VXLAN;
291+
pre_tun = nfp_fl_pre_tunnel(nfp_fl->action_data, *a_len);
292+
nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
293+
*a_len += sizeof(struct nfp_fl_pre_tunnel);
294+
295+
s_vxl = (struct nfp_fl_set_vxlan *)&nfp_fl->action_data[*a_len];
296+
err = nfp_fl_set_vxlan(s_vxl, a, pre_tun);
297+
if (err)
298+
return err;
299+
300+
*a_len += sizeof(struct nfp_fl_set_vxlan);
301+
} else if (is_tcf_tunnel_release(a)) {
302+
/* Tunnel decap is handled by default so accept action. */
303+
return 0;
173304
} else {
174305
/* Currently we do not handle any other actions. */
175306
return -EOPNOTSUPP;
@@ -182,18 +313,22 @@ int nfp_flower_compile_action(struct tc_cls_flower_offload *flow,
182313
struct net_device *netdev,
183314
struct nfp_fl_payload *nfp_flow)
184315
{
185-
int act_len, act_cnt, err;
316+
int act_len, act_cnt, err, tun_out_cnt;
317+
enum nfp_flower_tun_type tun_type;
186318
const struct tc_action *a;
187319
LIST_HEAD(actions);
188320

189321
memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ);
190322
nfp_flow->meta.act_len = 0;
323+
tun_type = NFP_FL_TUNNEL_NONE;
191324
act_len = 0;
192325
act_cnt = 0;
326+
tun_out_cnt = 0;
193327

194328
tcf_exts_to_list(flow->exts, &actions);
195329
list_for_each_entry(a, &actions, list) {
196-
err = nfp_flower_loop_action(a, nfp_flow, &act_len, netdev);
330+
err = nfp_flower_loop_action(a, nfp_flow, &act_len, netdev,
331+
&tun_type, &tun_out_cnt);
197332
if (err)
198333
return err;
199334
act_cnt++;

drivers/net/ethernet/netronome/nfp/flower/cmsg.h

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,12 @@
6767
#define NFP_FL_LW_SIZ 2
6868

6969
/* Action opcodes */
70-
#define NFP_FL_ACTION_OPCODE_OUTPUT 0
71-
#define NFP_FL_ACTION_OPCODE_PUSH_VLAN 1
72-
#define NFP_FL_ACTION_OPCODE_POP_VLAN 2
73-
#define NFP_FL_ACTION_OPCODE_NUM 32
70+
#define NFP_FL_ACTION_OPCODE_OUTPUT 0
71+
#define NFP_FL_ACTION_OPCODE_PUSH_VLAN 1
72+
#define NFP_FL_ACTION_OPCODE_POP_VLAN 2
73+
#define NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL 6
74+
#define NFP_FL_ACTION_OPCODE_PRE_TUNNEL 17
75+
#define NFP_FL_ACTION_OPCODE_NUM 32
7476

7577
#define NFP_FL_ACT_JMP_ID GENMASK(15, 8)
7678
#define NFP_FL_ACT_LEN_LW GENMASK(7, 0)
@@ -85,6 +87,8 @@
8587

8688
/* Tunnel ports */
8789
#define NFP_FL_PORT_TYPE_TUN 0x50000000
90+
#define NFP_FL_IPV4_TUNNEL_TYPE GENMASK(7, 4)
91+
#define NFP_FL_IPV4_PRE_TUN_INDEX GENMASK(2, 0)
8892

8993
enum nfp_flower_tun_type {
9094
NFP_FL_TUNNEL_NONE = 0,
@@ -123,6 +127,25 @@ struct nfp_flower_meta_one {
123127
u16 reserved;
124128
};
125129

130+
struct nfp_fl_pre_tunnel {
131+
__be16 a_op;
132+
__be16 reserved;
133+
__be32 ipv4_dst;
134+
/* reserved for use with IPv6 addresses */
135+
__be32 extra[3];
136+
};
137+
138+
struct nfp_fl_set_vxlan {
139+
__be16 a_op;
140+
__be16 reserved;
141+
__be64 tun_id;
142+
__be32 tun_type_index;
143+
__be16 tun_flags;
144+
u8 ipv4_ttl;
145+
u8 ipv4_tos;
146+
__be32 extra[2];
147+
} __packed;
148+
126149
/* Metadata with L2 (1W/4B)
127150
* ----------------------------------------------------------------
128151
* 3 2 1

0 commit comments

Comments
 (0)