Skip to content

Commit 75790a7

Browse files
committed
Merge branch 'nfp-more-set-actions-and-notifier-refactor'
Jakub Kicinski says: ==================== nfp: more set actions and notifier refactor This series brings updates to flower offload code. First Pieter adds support for setting TTL, ToS, Flow Label and Hop Limit fields in IPv4 and IPv6 headers. Remaining 5 patches deal with factoring out netdev notifiers from flower code. We already have two instances, and more is coming, so it's time to move to one central notifier which then feeds individual feature handlers. I start that part by cleaning up the existing notifiers. Next a central notifier is added, and used by flower offloads. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 6a02d1f + 0c665e2 commit 75790a7

File tree

8 files changed

+252
-104
lines changed

8 files changed

+252
-104
lines changed

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

Lines changed: 124 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -384,10 +384,21 @@ nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off,
384384
return 0;
385385
}
386386

387+
struct ipv4_ttl_word {
388+
__u8 ttl;
389+
__u8 protocol;
390+
__sum16 check;
391+
};
392+
387393
static int
388394
nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
389-
struct nfp_fl_set_ip4_addrs *set_ip_addr)
395+
struct nfp_fl_set_ip4_addrs *set_ip_addr,
396+
struct nfp_fl_set_ip4_ttl_tos *set_ip_ttl_tos)
390397
{
398+
struct ipv4_ttl_word *ttl_word_mask;
399+
struct ipv4_ttl_word *ttl_word;
400+
struct iphdr *tos_word_mask;
401+
struct iphdr *tos_word;
391402
__be32 exact, mask;
392403

393404
/* We are expecting tcf_pedit to return a big endian value */
@@ -402,20 +413,53 @@ nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
402413
set_ip_addr->ipv4_dst_mask |= mask;
403414
set_ip_addr->ipv4_dst &= ~mask;
404415
set_ip_addr->ipv4_dst |= exact & mask;
416+
set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
417+
set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >>
418+
NFP_FL_LW_SIZ;
405419
break;
406420
case offsetof(struct iphdr, saddr):
407421
set_ip_addr->ipv4_src_mask |= mask;
408422
set_ip_addr->ipv4_src &= ~mask;
409423
set_ip_addr->ipv4_src |= exact & mask;
424+
set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
425+
set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >>
426+
NFP_FL_LW_SIZ;
427+
break;
428+
case offsetof(struct iphdr, ttl):
429+
ttl_word_mask = (struct ipv4_ttl_word *)&mask;
430+
ttl_word = (struct ipv4_ttl_word *)&exact;
431+
432+
if (ttl_word_mask->protocol || ttl_word_mask->check)
433+
return -EOPNOTSUPP;
434+
435+
set_ip_ttl_tos->ipv4_ttl_mask |= ttl_word_mask->ttl;
436+
set_ip_ttl_tos->ipv4_ttl &= ~ttl_word_mask->ttl;
437+
set_ip_ttl_tos->ipv4_ttl |= ttl_word->ttl & ttl_word_mask->ttl;
438+
set_ip_ttl_tos->head.jump_id =
439+
NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
440+
set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >>
441+
NFP_FL_LW_SIZ;
442+
break;
443+
case round_down(offsetof(struct iphdr, tos), 4):
444+
tos_word_mask = (struct iphdr *)&mask;
445+
tos_word = (struct iphdr *)&exact;
446+
447+
if (tos_word_mask->version || tos_word_mask->ihl ||
448+
tos_word_mask->tot_len)
449+
return -EOPNOTSUPP;
450+
451+
set_ip_ttl_tos->ipv4_tos_mask |= tos_word_mask->tos;
452+
set_ip_ttl_tos->ipv4_tos &= ~tos_word_mask->tos;
453+
set_ip_ttl_tos->ipv4_tos |= tos_word->tos & tos_word_mask->tos;
454+
set_ip_ttl_tos->head.jump_id =
455+
NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
456+
set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >>
457+
NFP_FL_LW_SIZ;
410458
break;
411459
default:
412460
return -EOPNOTSUPP;
413461
}
414462

415-
set_ip_addr->reserved = cpu_to_be16(0);
416-
set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
417-
set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >> NFP_FL_LW_SIZ;
418-
419463
return 0;
420464
}
421465

@@ -432,12 +476,57 @@ nfp_fl_set_ip6_helper(int opcode_tag, u8 word, __be32 exact, __be32 mask,
432476
ip6->head.len_lw = sizeof(*ip6) >> NFP_FL_LW_SIZ;
433477
}
434478

479+
struct ipv6_hop_limit_word {
480+
__be16 payload_len;
481+
u8 nexthdr;
482+
u8 hop_limit;
483+
};
484+
485+
static int
486+
nfp_fl_set_ip6_hop_limit_flow_label(u32 off, __be32 exact, __be32 mask,
487+
struct nfp_fl_set_ipv6_tc_hl_fl *ip_hl_fl)
488+
{
489+
struct ipv6_hop_limit_word *fl_hl_mask;
490+
struct ipv6_hop_limit_word *fl_hl;
491+
492+
switch (off) {
493+
case offsetof(struct ipv6hdr, payload_len):
494+
fl_hl_mask = (struct ipv6_hop_limit_word *)&mask;
495+
fl_hl = (struct ipv6_hop_limit_word *)&exact;
496+
497+
if (fl_hl_mask->nexthdr || fl_hl_mask->payload_len)
498+
return -EOPNOTSUPP;
499+
500+
ip_hl_fl->ipv6_hop_limit_mask |= fl_hl_mask->hop_limit;
501+
ip_hl_fl->ipv6_hop_limit &= ~fl_hl_mask->hop_limit;
502+
ip_hl_fl->ipv6_hop_limit |= fl_hl->hop_limit &
503+
fl_hl_mask->hop_limit;
504+
break;
505+
case round_down(offsetof(struct ipv6hdr, flow_lbl), 4):
506+
if (mask & ~IPV6_FLOW_LABEL_MASK ||
507+
exact & ~IPV6_FLOW_LABEL_MASK)
508+
return -EOPNOTSUPP;
509+
510+
ip_hl_fl->ipv6_label_mask |= mask;
511+
ip_hl_fl->ipv6_label &= ~mask;
512+
ip_hl_fl->ipv6_label |= exact & mask;
513+
break;
514+
}
515+
516+
ip_hl_fl->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV6_TC_HL_FL;
517+
ip_hl_fl->head.len_lw = sizeof(*ip_hl_fl) >> NFP_FL_LW_SIZ;
518+
519+
return 0;
520+
}
521+
435522
static int
436523
nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off,
437524
struct nfp_fl_set_ipv6_addr *ip_dst,
438-
struct nfp_fl_set_ipv6_addr *ip_src)
525+
struct nfp_fl_set_ipv6_addr *ip_src,
526+
struct nfp_fl_set_ipv6_tc_hl_fl *ip_hl_fl)
439527
{
440528
__be32 exact, mask;
529+
int err = 0;
441530
u8 word;
442531

443532
/* We are expecting tcf_pedit to return a big endian value */
@@ -448,7 +537,8 @@ nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off,
448537
return -EOPNOTSUPP;
449538

450539
if (off < offsetof(struct ipv6hdr, saddr)) {
451-
return -EOPNOTSUPP;
540+
err = nfp_fl_set_ip6_hop_limit_flow_label(off, exact, mask,
541+
ip_hl_fl);
452542
} else if (off < offsetof(struct ipv6hdr, daddr)) {
453543
word = (off - offsetof(struct ipv6hdr, saddr)) / sizeof(exact);
454544
nfp_fl_set_ip6_helper(NFP_FL_ACTION_OPCODE_SET_IPV6_SRC, word,
@@ -462,7 +552,7 @@ nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off,
462552
return -EOPNOTSUPP;
463553
}
464554

465-
return 0;
555+
return err;
466556
}
467557

468558
static int
@@ -513,6 +603,8 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
513603
char *nfp_action, int *a_len, u32 *csum_updated)
514604
{
515605
struct nfp_fl_set_ipv6_addr set_ip6_dst, set_ip6_src;
606+
struct nfp_fl_set_ipv6_tc_hl_fl set_ip6_tc_hl_fl;
607+
struct nfp_fl_set_ip4_ttl_tos set_ip_ttl_tos;
516608
struct nfp_fl_set_ip4_addrs set_ip_addr;
517609
struct nfp_fl_set_tport set_tport;
518610
struct nfp_fl_set_eth set_eth;
@@ -522,6 +614,8 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
522614
u32 offset, cmd;
523615
u8 ip_proto = 0;
524616

617+
memset(&set_ip6_tc_hl_fl, 0, sizeof(set_ip6_tc_hl_fl));
618+
memset(&set_ip_ttl_tos, 0, sizeof(set_ip_ttl_tos));
525619
memset(&set_ip6_dst, 0, sizeof(set_ip6_dst));
526620
memset(&set_ip6_src, 0, sizeof(set_ip6_src));
527621
memset(&set_ip_addr, 0, sizeof(set_ip_addr));
@@ -542,11 +636,12 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
542636
err = nfp_fl_set_eth(action, idx, offset, &set_eth);
543637
break;
544638
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
545-
err = nfp_fl_set_ip4(action, idx, offset, &set_ip_addr);
639+
err = nfp_fl_set_ip4(action, idx, offset, &set_ip_addr,
640+
&set_ip_ttl_tos);
546641
break;
547642
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
548643
err = nfp_fl_set_ip6(action, idx, offset, &set_ip6_dst,
549-
&set_ip6_src);
644+
&set_ip6_src, &set_ip6_tc_hl_fl);
550645
break;
551646
case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP:
552647
err = nfp_fl_set_tport(action, idx, offset, &set_tport,
@@ -577,6 +672,16 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
577672
memcpy(nfp_action, &set_eth, act_size);
578673
*a_len += act_size;
579674
}
675+
if (set_ip_ttl_tos.head.len_lw) {
676+
nfp_action += act_size;
677+
act_size = sizeof(set_ip_ttl_tos);
678+
memcpy(nfp_action, &set_ip_ttl_tos, act_size);
679+
*a_len += act_size;
680+
681+
/* Hardware will automatically fix IPv4 and TCP/UDP checksum. */
682+
*csum_updated |= TCA_CSUM_UPDATE_FLAG_IPV4HDR |
683+
nfp_fl_csum_l4_to_flag(ip_proto);
684+
}
580685
if (set_ip_addr.head.len_lw) {
581686
nfp_action += act_size;
582687
act_size = sizeof(set_ip_addr);
@@ -587,6 +692,15 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow,
587692
*csum_updated |= TCA_CSUM_UPDATE_FLAG_IPV4HDR |
588693
nfp_fl_csum_l4_to_flag(ip_proto);
589694
}
695+
if (set_ip6_tc_hl_fl.head.len_lw) {
696+
nfp_action += act_size;
697+
act_size = sizeof(set_ip6_tc_hl_fl);
698+
memcpy(nfp_action, &set_ip6_tc_hl_fl, act_size);
699+
*a_len += act_size;
700+
701+
/* Hardware will automatically fix TCP/UDP checksum. */
702+
*csum_updated |= nfp_fl_csum_l4_to_flag(ip_proto);
703+
}
590704
if (set_ip6_dst.head.len_lw && set_ip6_src.head.len_lw) {
591705
/* TC compiles set src and dst IPv6 address as a single action,
592706
* the hardware requires this to be 2 separate actions.

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@
6565
#define NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL 6
6666
#define NFP_FL_ACTION_OPCODE_SET_ETHERNET 7
6767
#define NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS 9
68+
#define NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS 10
6869
#define NFP_FL_ACTION_OPCODE_SET_IPV6_SRC 11
6970
#define NFP_FL_ACTION_OPCODE_SET_IPV6_DST 12
71+
#define NFP_FL_ACTION_OPCODE_SET_IPV6_TC_HL_FL 13
7072
#define NFP_FL_ACTION_OPCODE_SET_UDP 14
7173
#define NFP_FL_ACTION_OPCODE_SET_TCP 15
7274
#define NFP_FL_ACTION_OPCODE_PRE_LAG 16
@@ -82,6 +84,8 @@
8284
#define NFP_FL_PUSH_VLAN_CFI BIT(12)
8385
#define NFP_FL_PUSH_VLAN_VID GENMASK(11, 0)
8486

87+
#define IPV6_FLOW_LABEL_MASK cpu_to_be32(0x000fffff)
88+
8589
/* LAG ports */
8690
#define NFP_FL_LAG_OUT 0xC0DE0000
8791

@@ -125,6 +129,26 @@ struct nfp_fl_set_ip4_addrs {
125129
__be32 ipv4_dst;
126130
};
127131

132+
struct nfp_fl_set_ip4_ttl_tos {
133+
struct nfp_fl_act_head head;
134+
u8 ipv4_ttl_mask;
135+
u8 ipv4_tos_mask;
136+
u8 ipv4_ttl;
137+
u8 ipv4_tos;
138+
__be16 reserved;
139+
};
140+
141+
struct nfp_fl_set_ipv6_tc_hl_fl {
142+
struct nfp_fl_act_head head;
143+
u8 ipv6_tc_mask;
144+
u8 ipv6_hop_limit_mask;
145+
__be16 reserved;
146+
u8 ipv6_tc;
147+
u8 ipv6_hop_limit;
148+
__be32 ipv6_label_mask;
149+
__be32 ipv6_label;
150+
};
151+
128152
struct nfp_fl_set_ipv6_addr {
129153
struct nfp_fl_act_head head;
130154
__be16 reserved;

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

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -472,25 +472,32 @@ nfp_fl_lag_schedule_group_remove(struct nfp_fl_lag *lag,
472472
schedule_delayed_work(&lag->work, NFP_FL_LAG_DELAY);
473473
}
474474

475-
static int
475+
static void
476476
nfp_fl_lag_schedule_group_delete(struct nfp_fl_lag *lag,
477477
struct net_device *master)
478478
{
479479
struct nfp_fl_lag_group *group;
480+
struct nfp_flower_priv *priv;
481+
482+
priv = container_of(lag, struct nfp_flower_priv, nfp_lag);
483+
484+
if (!netif_is_bond_master(master))
485+
return;
480486

481487
mutex_lock(&lag->lock);
482488
group = nfp_fl_lag_find_group_for_master_with_lag(lag, master);
483489
if (!group) {
484490
mutex_unlock(&lag->lock);
485-
return -ENOENT;
491+
nfp_warn(priv->app->cpp, "untracked bond got unregistered %s\n",
492+
netdev_name(master));
493+
return;
486494
}
487495

488496
group->to_remove = true;
489497
group->to_destroy = true;
490498
mutex_unlock(&lag->lock);
491499

492500
schedule_delayed_work(&lag->work, NFP_FL_LAG_DELAY);
493-
return 0;
494501
}
495502

496503
static int
@@ -575,7 +582,7 @@ nfp_fl_lag_changeupper_event(struct nfp_fl_lag *lag,
575582
return 0;
576583
}
577584

578-
static int
585+
static void
579586
nfp_fl_lag_changels_event(struct nfp_fl_lag *lag, struct net_device *netdev,
580587
struct netdev_notifier_changelowerstate_info *info)
581588
{
@@ -586,18 +593,18 @@ nfp_fl_lag_changels_event(struct nfp_fl_lag *lag, struct net_device *netdev,
586593
unsigned long *flags;
587594

588595
if (!netif_is_lag_port(netdev) || !nfp_netdev_is_nfp_repr(netdev))
589-
return 0;
596+
return;
590597

591598
lag_lower_info = info->lower_state_info;
592599
if (!lag_lower_info)
593-
return 0;
600+
return;
594601

595602
priv = container_of(lag, struct nfp_flower_priv, nfp_lag);
596603
repr = netdev_priv(netdev);
597604

598605
/* Verify that the repr is associated with this app. */
599606
if (repr->app != priv->app)
600-
return 0;
607+
return;
601608

602609
repr_priv = repr->app_priv;
603610
flags = &repr_priv->lag_port_flags;
@@ -617,38 +624,27 @@ nfp_fl_lag_changels_event(struct nfp_fl_lag *lag, struct net_device *netdev,
617624
mutex_unlock(&lag->lock);
618625

619626
schedule_delayed_work(&lag->work, NFP_FL_LAG_DELAY);
620-
return 0;
621627
}
622628

623-
static int
624-
nfp_fl_lag_netdev_event(struct notifier_block *nb, unsigned long event,
625-
void *ptr)
629+
int nfp_flower_lag_netdev_event(struct nfp_flower_priv *priv,
630+
struct net_device *netdev,
631+
unsigned long event, void *ptr)
626632
{
627-
struct net_device *netdev;
628-
struct nfp_fl_lag *lag;
633+
struct nfp_fl_lag *lag = &priv->nfp_lag;
629634
int err;
630635

631-
netdev = netdev_notifier_info_to_dev(ptr);
632-
lag = container_of(nb, struct nfp_fl_lag, lag_nb);
633-
634636
switch (event) {
635637
case NETDEV_CHANGEUPPER:
636638
err = nfp_fl_lag_changeupper_event(lag, ptr);
637639
if (err)
638640
return NOTIFY_BAD;
639641
return NOTIFY_OK;
640642
case NETDEV_CHANGELOWERSTATE:
641-
err = nfp_fl_lag_changels_event(lag, netdev, ptr);
642-
if (err)
643-
return NOTIFY_BAD;
643+
nfp_fl_lag_changels_event(lag, netdev, ptr);
644644
return NOTIFY_OK;
645645
case NETDEV_UNREGISTER:
646-
if (netif_is_bond_master(netdev)) {
647-
err = nfp_fl_lag_schedule_group_delete(lag, netdev);
648-
if (err)
649-
return NOTIFY_BAD;
650-
return NOTIFY_OK;
651-
}
646+
nfp_fl_lag_schedule_group_delete(lag, netdev);
647+
return NOTIFY_OK;
652648
}
653649

654650
return NOTIFY_DONE;
@@ -673,8 +669,6 @@ void nfp_flower_lag_init(struct nfp_fl_lag *lag)
673669

674670
/* 0 is a reserved batch version so increment to first valid value. */
675671
nfp_fl_increment_version(lag);
676-
677-
lag->lag_nb.notifier_call = nfp_fl_lag_netdev_event;
678672
}
679673

680674
void nfp_flower_lag_cleanup(struct nfp_fl_lag *lag)

0 commit comments

Comments
 (0)