1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2015-2018 Netronome Systems, Inc. */
4 #include <linux/bitfield.h>
5 #include <linux/netdevice.h>
6 #include <linux/skbuff.h>
7 #include <linux/workqueue.h>
8 #include <net/dst_metadata.h>
11 #include "../nfp_net.h"
12 #include "../nfp_net_repr.h"
15 static struct nfp_flower_cmsg_hdr
*
16 nfp_flower_cmsg_get_hdr(struct sk_buff
*skb
)
18 return (struct nfp_flower_cmsg_hdr
*)skb
->data
;
22 nfp_flower_cmsg_alloc(struct nfp_app
*app
, unsigned int size
,
23 enum nfp_flower_cmsg_type_port type
, gfp_t flag
)
25 struct nfp_flower_cmsg_hdr
*ch
;
28 size
+= NFP_FLOWER_CMSG_HLEN
;
30 skb
= nfp_app_ctrl_msg_alloc(app
, size
, flag
);
34 ch
= nfp_flower_cmsg_get_hdr(skb
);
36 ch
->version
= NFP_FLOWER_CMSG_VER1
;
44 nfp_flower_cmsg_mac_repr_start(struct nfp_app
*app
, unsigned int num_ports
)
46 struct nfp_flower_cmsg_mac_repr
*msg
;
49 skb
= nfp_flower_cmsg_alloc(app
, struct_size(msg
, ports
, num_ports
),
50 NFP_FLOWER_CMSG_TYPE_MAC_REPR
, GFP_KERNEL
);
54 msg
= nfp_flower_cmsg_get_data(skb
);
55 memset(msg
->reserved
, 0, sizeof(msg
->reserved
));
56 msg
->num_ports
= num_ports
;
62 nfp_flower_cmsg_mac_repr_add(struct sk_buff
*skb
, unsigned int idx
,
63 unsigned int nbi
, unsigned int nbi_port
,
64 unsigned int phys_port
)
66 struct nfp_flower_cmsg_mac_repr
*msg
;
68 msg
= nfp_flower_cmsg_get_data(skb
);
69 msg
->ports
[idx
].idx
= idx
;
70 msg
->ports
[idx
].info
= nbi
& NFP_FLOWER_CMSG_MAC_REPR_NBI
;
71 msg
->ports
[idx
].nbi_port
= nbi_port
;
72 msg
->ports
[idx
].phys_port
= phys_port
;
75 int nfp_flower_cmsg_portmod(struct nfp_repr
*repr
, bool carrier_ok
,
76 unsigned int mtu
, bool mtu_only
)
78 struct nfp_flower_cmsg_portmod
*msg
;
81 skb
= nfp_flower_cmsg_alloc(repr
->app
, sizeof(*msg
),
82 NFP_FLOWER_CMSG_TYPE_PORT_MOD
, GFP_KERNEL
);
86 msg
= nfp_flower_cmsg_get_data(skb
);
87 msg
->portnum
= cpu_to_be32(repr
->dst
->u
.port_info
.port_id
);
89 msg
->info
= carrier_ok
;
92 msg
->info
|= NFP_FLOWER_CMSG_PORTMOD_MTU_CHANGE_ONLY
;
94 msg
->mtu
= cpu_to_be16(mtu
);
96 nfp_ctrl_tx(repr
->app
->ctrl
, skb
);
101 int nfp_flower_cmsg_portreify(struct nfp_repr
*repr
, bool exists
)
103 struct nfp_flower_cmsg_portreify
*msg
;
106 skb
= nfp_flower_cmsg_alloc(repr
->app
, sizeof(*msg
),
107 NFP_FLOWER_CMSG_TYPE_PORT_REIFY
,
112 msg
= nfp_flower_cmsg_get_data(skb
);
113 msg
->portnum
= cpu_to_be32(repr
->dst
->u
.port_info
.port_id
);
115 msg
->info
= cpu_to_be16(exists
);
117 nfp_ctrl_tx(repr
->app
->ctrl
, skb
);
123 nfp_flower_process_mtu_ack(struct nfp_app
*app
, struct sk_buff
*skb
)
125 struct nfp_flower_priv
*app_priv
= app
->priv
;
126 struct nfp_flower_cmsg_portmod
*msg
;
128 msg
= nfp_flower_cmsg_get_data(skb
);
130 if (!(msg
->info
& NFP_FLOWER_CMSG_PORTMOD_MTU_CHANGE_ONLY
))
133 spin_lock_bh(&app_priv
->mtu_conf
.lock
);
134 if (!app_priv
->mtu_conf
.requested_val
||
135 app_priv
->mtu_conf
.portnum
!= be32_to_cpu(msg
->portnum
) ||
136 be16_to_cpu(msg
->mtu
) != app_priv
->mtu_conf
.requested_val
) {
137 /* Not an ack for requested MTU change. */
138 spin_unlock_bh(&app_priv
->mtu_conf
.lock
);
142 app_priv
->mtu_conf
.ack
= true;
143 app_priv
->mtu_conf
.requested_val
= 0;
144 wake_up(&app_priv
->mtu_conf
.wait_q
);
145 spin_unlock_bh(&app_priv
->mtu_conf
.lock
);
151 nfp_flower_cmsg_portmod_rx(struct nfp_app
*app
, struct sk_buff
*skb
)
153 struct nfp_flower_cmsg_portmod
*msg
;
154 struct net_device
*netdev
;
157 msg
= nfp_flower_cmsg_get_data(skb
);
158 link
= msg
->info
& NFP_FLOWER_CMSG_PORTMOD_INFO_LINK
;
162 netdev
= nfp_app_dev_get(app
, be32_to_cpu(msg
->portnum
), NULL
);
165 nfp_flower_cmsg_warn(app
, "ctrl msg for unknown port 0x%08x\n",
166 be32_to_cpu(msg
->portnum
));
172 u16 mtu
= be16_to_cpu(msg
->mtu
);
174 netif_carrier_on(netdev
);
176 /* An MTU of 0 from the firmware should be ignored */
178 dev_set_mtu(netdev
, mtu
);
180 netif_carrier_off(netdev
);
186 nfp_flower_cmsg_portreify_rx(struct nfp_app
*app
, struct sk_buff
*skb
)
188 struct nfp_flower_priv
*priv
= app
->priv
;
189 struct nfp_flower_cmsg_portreify
*msg
;
192 msg
= nfp_flower_cmsg_get_data(skb
);
195 exists
= !!nfp_app_dev_get(app
, be32_to_cpu(msg
->portnum
), NULL
);
198 nfp_flower_cmsg_warn(app
, "ctrl msg for unknown port 0x%08x\n",
199 be32_to_cpu(msg
->portnum
));
203 atomic_inc(&priv
->reify_replies
);
204 wake_up(&priv
->reify_wait_queue
);
208 nfp_flower_cmsg_merge_hint_rx(struct nfp_app
*app
, struct sk_buff
*skb
)
210 unsigned int msg_len
= nfp_flower_cmsg_get_data_len(skb
);
211 struct nfp_flower_cmsg_merge_hint
*msg
;
212 struct nfp_fl_payload
*sub_flows
[2];
213 int err
, i
, flow_cnt
;
215 msg
= nfp_flower_cmsg_get_data(skb
);
216 /* msg->count starts at 0 and always assumes at least 1 entry. */
217 flow_cnt
= msg
->count
+ 1;
219 if (msg_len
< struct_size(msg
, flow
, flow_cnt
)) {
220 nfp_flower_cmsg_warn(app
, "Merge hint ctrl msg too short - %d bytes but expect %zd\n",
221 msg_len
, struct_size(msg
, flow
, flow_cnt
));
226 nfp_flower_cmsg_warn(app
, "Merge hint contains %d flows - two are expected\n",
232 for (i
= 0; i
< flow_cnt
; i
++) {
233 u32 ctx
= be32_to_cpu(msg
->flow
[i
].host_ctx
);
235 sub_flows
[i
] = nfp_flower_get_fl_payload_from_ctx(app
, ctx
);
237 nfp_flower_cmsg_warn(app
, "Invalid flow in merge hint\n");
238 goto err_rtnl_unlock
;
242 err
= nfp_flower_merge_offloaded_flows(app
, sub_flows
[0], sub_flows
[1]);
243 /* Only warn on memory fail. Hint veto will not break functionality. */
245 nfp_flower_cmsg_warn(app
, "Flow merge memory fail.\n");
252 nfp_flower_cmsg_process_one_rx(struct nfp_app
*app
, struct sk_buff
*skb
)
254 struct nfp_flower_priv
*app_priv
= app
->priv
;
255 struct nfp_flower_cmsg_hdr
*cmsg_hdr
;
256 enum nfp_flower_cmsg_type_port type
;
257 bool skb_stored
= false;
259 cmsg_hdr
= nfp_flower_cmsg_get_hdr(skb
);
261 type
= cmsg_hdr
->type
;
263 case NFP_FLOWER_CMSG_TYPE_PORT_MOD
:
264 nfp_flower_cmsg_portmod_rx(app
, skb
);
266 case NFP_FLOWER_CMSG_TYPE_MERGE_HINT
:
267 if (app_priv
->flower_en_feats
& NFP_FL_ENABLE_FLOW_MERGE
) {
268 nfp_flower_cmsg_merge_hint_rx(app
, skb
);
272 case NFP_FLOWER_CMSG_TYPE_NO_NEIGH
:
273 nfp_tunnel_request_route_v4(app
, skb
);
275 case NFP_FLOWER_CMSG_TYPE_NO_NEIGH_V6
:
276 nfp_tunnel_request_route_v6(app
, skb
);
278 case NFP_FLOWER_CMSG_TYPE_ACTIVE_TUNS
:
279 nfp_tunnel_keep_alive(app
, skb
);
281 case NFP_FLOWER_CMSG_TYPE_ACTIVE_TUNS_V6
:
282 nfp_tunnel_keep_alive_v6(app
, skb
);
284 case NFP_FLOWER_CMSG_TYPE_QOS_STATS
:
285 nfp_flower_stats_rlim_reply(app
, skb
);
287 case NFP_FLOWER_CMSG_TYPE_LAG_CONFIG
:
288 if (app_priv
->flower_en_feats
& NFP_FL_ENABLE_LAG
) {
289 skb_stored
= nfp_flower_lag_unprocessed_msg(app
, skb
);
295 nfp_flower_cmsg_warn(app
, "Cannot handle invalid repr control type %u\n",
301 dev_consume_skb_any(skb
);
304 dev_kfree_skb_any(skb
);
307 void nfp_flower_cmsg_process_rx(struct work_struct
*work
)
309 struct sk_buff_head cmsg_joined
;
310 struct nfp_flower_priv
*priv
;
313 priv
= container_of(work
, struct nfp_flower_priv
, cmsg_work
);
314 skb_queue_head_init(&cmsg_joined
);
316 spin_lock_bh(&priv
->cmsg_skbs_high
.lock
);
317 skb_queue_splice_tail_init(&priv
->cmsg_skbs_high
, &cmsg_joined
);
318 spin_unlock_bh(&priv
->cmsg_skbs_high
.lock
);
320 spin_lock_bh(&priv
->cmsg_skbs_low
.lock
);
321 skb_queue_splice_tail_init(&priv
->cmsg_skbs_low
, &cmsg_joined
);
322 spin_unlock_bh(&priv
->cmsg_skbs_low
.lock
);
324 while ((skb
= __skb_dequeue(&cmsg_joined
)))
325 nfp_flower_cmsg_process_one_rx(priv
->app
, skb
);
329 nfp_flower_queue_ctl_msg(struct nfp_app
*app
, struct sk_buff
*skb
, int type
)
331 struct nfp_flower_priv
*priv
= app
->priv
;
332 struct sk_buff_head
*skb_head
;
334 if (type
== NFP_FLOWER_CMSG_TYPE_PORT_MOD
)
335 skb_head
= &priv
->cmsg_skbs_high
;
337 skb_head
= &priv
->cmsg_skbs_low
;
339 if (skb_queue_len(skb_head
) >= NFP_FLOWER_WORKQ_MAX_SKBS
) {
340 nfp_flower_cmsg_warn(app
, "Dropping queued control messages\n");
341 dev_kfree_skb_any(skb
);
345 skb_queue_tail(skb_head
, skb
);
346 schedule_work(&priv
->cmsg_work
);
349 void nfp_flower_cmsg_rx(struct nfp_app
*app
, struct sk_buff
*skb
)
351 struct nfp_flower_cmsg_hdr
*cmsg_hdr
;
353 cmsg_hdr
= nfp_flower_cmsg_get_hdr(skb
);
355 if (unlikely(cmsg_hdr
->version
!= NFP_FLOWER_CMSG_VER1
)) {
356 nfp_flower_cmsg_warn(app
, "Cannot handle repr control version %u\n",
358 dev_kfree_skb_any(skb
);
362 if (cmsg_hdr
->type
== NFP_FLOWER_CMSG_TYPE_FLOW_STATS
) {
363 /* We need to deal with stats updates from HW asap */
364 nfp_flower_rx_flow_stats(app
, skb
);
365 dev_consume_skb_any(skb
);
366 } else if (cmsg_hdr
->type
== NFP_FLOWER_CMSG_TYPE_PORT_MOD
&&
367 nfp_flower_process_mtu_ack(app
, skb
)) {
368 /* Handle MTU acks outside wq to prevent RTNL conflict. */
369 dev_consume_skb_any(skb
);
370 } else if (cmsg_hdr
->type
== NFP_FLOWER_CMSG_TYPE_TUN_NEIGH
||
371 cmsg_hdr
->type
== NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6
) {
372 /* Acks from the NFP that the route is added - ignore. */
373 dev_consume_skb_any(skb
);
374 } else if (cmsg_hdr
->type
== NFP_FLOWER_CMSG_TYPE_PORT_REIFY
) {
375 /* Handle REIFY acks outside wq to prevent RTNL conflict. */
376 nfp_flower_cmsg_portreify_rx(app
, skb
);
377 dev_consume_skb_any(skb
);
379 nfp_flower_queue_ctl_msg(app
, skb
, cmsg_hdr
->type
);