Skip to content

Commit 59b328c

Browse files
chelsiocudbgdavem330
authored andcommitted
cxgb4: add TC-MATCHALL IPv6 support
Matching IPv6 traffic require allocating their own individual slots in TCAM. So, fetch additional slots to insert IPv6 rules. Also, fetch the cumulative stats of all the slots occupied by the Matchall rule. Signed-off-by: Rahul Lakkireddy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent af9fdd2 commit 59b328c

File tree

3 files changed

+82
-26
lines changed

3 files changed

+82
-26
lines changed

drivers/net/ethernet/chelsio/cxgb4/cxgb4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,6 +1438,8 @@ enum {
14381438
NAT_MODE_ALL /* NAT on entire 4-tuple */
14391439
};
14401440

1441+
#define CXGB4_FILTER_TYPE_MAX 2
1442+
14411443
/* Host shadow copy of ingress filter entry. This is in host native format
14421444
* and doesn't match the ordering or bit order, etc. of the hardware of the
14431445
* firmware command. The use of bit-field structure elements is purely to

drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c

Lines changed: 77 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,26 @@ static void cxgb4_matchall_mirror_free(struct net_device *dev)
231231
tc_port_matchall->ingress.viid_mirror = 0;
232232
}
233233

234-
static int cxgb4_matchall_alloc_filter(struct net_device *dev,
235-
struct tc_cls_matchall_offload *cls)
234+
static int cxgb4_matchall_del_filter(struct net_device *dev, u8 filter_type)
235+
{
236+
struct cxgb4_tc_port_matchall *tc_port_matchall;
237+
struct port_info *pi = netdev2pinfo(dev);
238+
struct adapter *adap = netdev2adap(dev);
239+
int ret;
240+
241+
tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
242+
ret = cxgb4_del_filter(dev, tc_port_matchall->ingress.tid[filter_type],
243+
&tc_port_matchall->ingress.fs[filter_type]);
244+
if (ret)
245+
return ret;
246+
247+
tc_port_matchall->ingress.tid[filter_type] = 0;
248+
return 0;
249+
}
250+
251+
static int cxgb4_matchall_add_filter(struct net_device *dev,
252+
struct tc_cls_matchall_offload *cls,
253+
u8 filter_type)
236254
{
237255
struct netlink_ext_ack *extack = cls->common.extack;
238256
struct cxgb4_tc_port_matchall *tc_port_matchall;
@@ -244,28 +262,24 @@ static int cxgb4_matchall_alloc_filter(struct net_device *dev,
244262
/* Get a free filter entry TID, where we can insert this new
245263
* rule. Only insert rule if its prio doesn't conflict with
246264
* existing rules.
247-
*
248-
* 1 slot is enough to create a wildcard matchall VIID rule.
249265
*/
250-
fidx = cxgb4_get_free_ftid(dev, PF_INET, false, cls->common.prio);
266+
fidx = cxgb4_get_free_ftid(dev, filter_type ? PF_INET6 : PF_INET,
267+
false, cls->common.prio);
251268
if (fidx < 0) {
252269
NL_SET_ERR_MSG_MOD(extack,
253270
"No free LETCAM index available");
254271
return -ENOMEM;
255272
}
256273

257-
ret = cxgb4_matchall_mirror_alloc(dev, cls);
258-
if (ret)
259-
return ret;
260-
261274
tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
262-
fs = &tc_port_matchall->ingress.fs;
275+
fs = &tc_port_matchall->ingress.fs[filter_type];
263276
memset(fs, 0, sizeof(*fs));
264277

265278
if (fidx < adap->tids.nhpftids)
266279
fs->prio = 1;
267280
fs->tc_prio = cls->common.prio;
268281
fs->tc_cookie = cls->cookie;
282+
fs->type = filter_type;
269283
fs->hitcnts = 1;
270284

271285
fs->val.pfvf_vld = 1;
@@ -276,13 +290,39 @@ static int cxgb4_matchall_alloc_filter(struct net_device *dev,
276290

277291
ret = cxgb4_set_filter(dev, fidx, fs);
278292
if (ret)
279-
goto out_free;
293+
return ret;
294+
295+
tc_port_matchall->ingress.tid[filter_type] = fidx;
296+
return 0;
297+
}
298+
299+
static int cxgb4_matchall_alloc_filter(struct net_device *dev,
300+
struct tc_cls_matchall_offload *cls)
301+
{
302+
struct cxgb4_tc_port_matchall *tc_port_matchall;
303+
struct port_info *pi = netdev2pinfo(dev);
304+
struct adapter *adap = netdev2adap(dev);
305+
int ret, i;
306+
307+
tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
308+
309+
ret = cxgb4_matchall_mirror_alloc(dev, cls);
310+
if (ret)
311+
return ret;
312+
313+
for (i = 0; i < CXGB4_FILTER_TYPE_MAX; i++) {
314+
ret = cxgb4_matchall_add_filter(dev, cls, i);
315+
if (ret)
316+
goto out_free;
317+
}
280318

281-
tc_port_matchall->ingress.tid = fidx;
282319
tc_port_matchall->ingress.state = CXGB4_MATCHALL_STATE_ENABLED;
283320
return 0;
284321

285322
out_free:
323+
while (i-- > 0)
324+
cxgb4_matchall_del_filter(dev, i);
325+
286326
cxgb4_matchall_mirror_free(dev);
287327
return ret;
288328
}
@@ -293,20 +333,21 @@ static int cxgb4_matchall_free_filter(struct net_device *dev)
293333
struct port_info *pi = netdev2pinfo(dev);
294334
struct adapter *adap = netdev2adap(dev);
295335
int ret;
336+
u8 i;
296337

297338
tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
298339

299-
ret = cxgb4_del_filter(dev, tc_port_matchall->ingress.tid,
300-
&tc_port_matchall->ingress.fs);
301-
if (ret)
302-
return ret;
340+
for (i = 0; i < CXGB4_FILTER_TYPE_MAX; i++) {
341+
ret = cxgb4_matchall_del_filter(dev, i);
342+
if (ret)
343+
return ret;
344+
}
303345

304346
cxgb4_matchall_mirror_free(dev);
305347

306348
tc_port_matchall->ingress.packets = 0;
307349
tc_port_matchall->ingress.bytes = 0;
308350
tc_port_matchall->ingress.last_used = 0;
309-
tc_port_matchall->ingress.tid = 0;
310351
tc_port_matchall->ingress.state = CXGB4_MATCHALL_STATE_DISABLED;
311352
return 0;
312353
}
@@ -362,8 +403,12 @@ int cxgb4_tc_matchall_destroy(struct net_device *dev,
362403

363404
tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
364405
if (ingress) {
406+
/* All the filter types of this matchall rule save the
407+
* same cookie. So, checking for the first one is
408+
* enough.
409+
*/
365410
if (cls_matchall->cookie !=
366-
tc_port_matchall->ingress.fs.tc_cookie)
411+
tc_port_matchall->ingress.fs[0].tc_cookie)
367412
return -ENOENT;
368413

369414
return cxgb4_matchall_free_filter(dev);
@@ -379,21 +424,29 @@ int cxgb4_tc_matchall_destroy(struct net_device *dev,
379424
int cxgb4_tc_matchall_stats(struct net_device *dev,
380425
struct tc_cls_matchall_offload *cls_matchall)
381426
{
427+
u64 tmp_packets, tmp_bytes, packets = 0, bytes = 0;
382428
struct cxgb4_tc_port_matchall *tc_port_matchall;
429+
struct cxgb4_matchall_ingress_entry *ingress;
383430
struct port_info *pi = netdev2pinfo(dev);
384431
struct adapter *adap = netdev2adap(dev);
385-
u64 packets, bytes;
386432
int ret;
433+
u8 i;
387434

388435
tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
389436
if (tc_port_matchall->ingress.state == CXGB4_MATCHALL_STATE_DISABLED)
390437
return -ENOENT;
391438

392-
ret = cxgb4_get_filter_counters(dev, tc_port_matchall->ingress.tid,
393-
&packets, &bytes,
394-
tc_port_matchall->ingress.fs.hash);
395-
if (ret)
396-
return ret;
439+
ingress = &tc_port_matchall->ingress;
440+
for (i = 0; i < CXGB4_FILTER_TYPE_MAX; i++) {
441+
ret = cxgb4_get_filter_counters(dev, ingress->tid[i],
442+
&tmp_packets, &tmp_bytes,
443+
ingress->fs[i].hash);
444+
if (ret)
445+
return ret;
446+
447+
packets += tmp_packets;
448+
bytes += tmp_bytes;
449+
}
397450

398451
if (tc_port_matchall->ingress.packets != packets) {
399452
flow_stats_update(&cls_matchall->stats,

drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ struct cxgb4_matchall_egress_entry {
1919

2020
struct cxgb4_matchall_ingress_entry {
2121
enum cxgb4_matchall_state state; /* Current MATCHALL offload state */
22-
u32 tid; /* Index to hardware filter entry */
23-
struct ch_filter_specification fs; /* Filter entry */
22+
u32 tid[CXGB4_FILTER_TYPE_MAX]; /* Index to hardware filter entries */
23+
/* Filter entries */
24+
struct ch_filter_specification fs[CXGB4_FILTER_TYPE_MAX];
2425
u16 viid_mirror; /* Identifier for allocated Mirror VI */
2526
u64 bytes; /* # of bytes hitting the filter */
2627
u64 packets; /* # of packets hitting the filter */

0 commit comments

Comments
 (0)