Skip to content

Commit

Permalink
nfp: flower: implement host cmsg handler for LAG
Browse files Browse the repository at this point in the history
Adds the control message handler to synchronize offloaded group config
with that of the kernel. Such messages are sent from fw to driver and
feature the following 3 flags:

- Data: an attached cmsg could not be processed - store for retransmission
- Xon: FW can accept new messages - retransmit any stored cmsgs
- Sync: full sync requested so retransmit all kernel LAG group info

Signed-off-by: John Hurley <john.hurley@netronome.com>
Reviewed-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
John Hurley authored and David S. Miller committed May 25, 2018
1 parent bb9a8d0 commit 2e1cc52
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 2 deletions.
8 changes: 6 additions & 2 deletions drivers/net/ethernet/netronome/nfp/flower/cmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)
struct nfp_flower_priv *app_priv = app->priv;
struct nfp_flower_cmsg_hdr *cmsg_hdr;
enum nfp_flower_cmsg_type_port type;
bool skb_stored = false;

cmsg_hdr = nfp_flower_cmsg_get_hdr(skb);

Expand All @@ -260,16 +261,19 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)
nfp_tunnel_keep_alive(app, skb);
break;
case NFP_FLOWER_CMSG_TYPE_LAG_CONFIG:
if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG)
if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) {
skb_stored = nfp_flower_lag_unprocessed_msg(app, skb);
break;
}
/* fall through */
default:
nfp_flower_cmsg_warn(app, "Cannot handle invalid repr control type %u\n",
type);
goto out;
}

dev_consume_skb_any(skb);
if (!skb_stored)
dev_consume_skb_any(skb);
return;
out:
dev_kfree_skb_any(skb);
Expand Down
95 changes: 95 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/lag_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
/* LAG group config flags. */
#define NFP_FL_LAG_LAST BIT(1)
#define NFP_FL_LAG_FIRST BIT(2)
#define NFP_FL_LAG_DATA BIT(3)
#define NFP_FL_LAG_XON BIT(4)
#define NFP_FL_LAG_SYNC BIT(5)
#define NFP_FL_LAG_SWITCH BIT(6)
#define NFP_FL_LAG_RESET BIT(7)

Expand Down Expand Up @@ -108,6 +111,8 @@ struct nfp_fl_lag_group {
/* wait for more config */
#define NFP_FL_LAG_DELAY (msecs_to_jiffies(2))

#define NFP_FL_LAG_RETRANS_LIMIT 100 /* max retrans cmsgs to store */

static unsigned int nfp_fl_get_next_pkt_number(struct nfp_fl_lag *lag)
{
lag->pkt_num++;
Expand Down Expand Up @@ -360,6 +365,92 @@ static void nfp_fl_lag_do_work(struct work_struct *work)
mutex_unlock(&lag->lock);
}

static int
nfp_fl_lag_put_unprocessed(struct nfp_fl_lag *lag, struct sk_buff *skb)
{
struct nfp_flower_cmsg_lag_config *cmsg_payload;

cmsg_payload = nfp_flower_cmsg_get_data(skb);
if (be32_to_cpu(cmsg_payload->group_id) >= NFP_FL_LAG_GROUP_MAX)
return -EINVAL;

/* Drop cmsg retrans if storage limit is exceeded to prevent
* overloading. If the fw notices that expected messages have not been
* received in a given time block, it will request a full resync.
*/
if (skb_queue_len(&lag->retrans_skbs) >= NFP_FL_LAG_RETRANS_LIMIT)
return -ENOSPC;

__skb_queue_tail(&lag->retrans_skbs, skb);

return 0;
}

static void nfp_fl_send_unprocessed(struct nfp_fl_lag *lag)
{
struct nfp_flower_priv *priv;
struct sk_buff *skb;

priv = container_of(lag, struct nfp_flower_priv, nfp_lag);

while ((skb = __skb_dequeue(&lag->retrans_skbs)))
nfp_ctrl_tx(priv->app->ctrl, skb);
}

bool nfp_flower_lag_unprocessed_msg(struct nfp_app *app, struct sk_buff *skb)
{
struct nfp_flower_cmsg_lag_config *cmsg_payload;
struct nfp_flower_priv *priv = app->priv;
struct nfp_fl_lag_group *group_entry;
unsigned long int flags;
bool store_skb = false;
int err;

cmsg_payload = nfp_flower_cmsg_get_data(skb);
flags = cmsg_payload->ctrl_flags;

/* Note the intentional fall through below. If DATA and XON are both
* set, the message will stored and sent again with the rest of the
* unprocessed messages list.
*/

/* Store */
if (flags & NFP_FL_LAG_DATA)
if (!nfp_fl_lag_put_unprocessed(&priv->nfp_lag, skb))
store_skb = true;

/* Send stored */
if (flags & NFP_FL_LAG_XON)
nfp_fl_send_unprocessed(&priv->nfp_lag);

/* Resend all */
if (flags & NFP_FL_LAG_SYNC) {
/* To resend all config:
* 1) Clear all unprocessed messages
* 2) Mark all groups dirty
* 3) Reset NFP group config
* 4) Schedule a LAG config update
*/

__skb_queue_purge(&priv->nfp_lag.retrans_skbs);

mutex_lock(&priv->nfp_lag.lock);
list_for_each_entry(group_entry, &priv->nfp_lag.group_list,
list)
group_entry->dirty = true;

err = nfp_flower_lag_reset(&priv->nfp_lag);
if (err)
nfp_flower_cmsg_warn(priv->app,
"mem err in group reset msg\n");
mutex_unlock(&priv->nfp_lag.lock);

schedule_delayed_work(&priv->nfp_lag.work, 0);
}

return store_skb;
}

static void
nfp_fl_lag_schedule_group_remove(struct nfp_fl_lag *lag,
struct nfp_fl_lag_group *group)
Expand Down Expand Up @@ -565,6 +656,8 @@ void nfp_flower_lag_init(struct nfp_fl_lag *lag)
mutex_init(&lag->lock);
ida_init(&lag->ida_handle);

__skb_queue_head_init(&lag->retrans_skbs);

/* 0 is a reserved batch version so increment to first valid value. */
nfp_fl_increment_version(lag);

Expand All @@ -577,6 +670,8 @@ void nfp_flower_lag_cleanup(struct nfp_fl_lag *lag)

cancel_delayed_work_sync(&lag->work);

__skb_queue_purge(&lag->retrans_skbs);

/* Remove all groups. */
mutex_lock(&lag->lock);
list_for_each_entry_safe(entry, storage, &lag->group_list, list) {
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ struct nfp_mtu_conf {
* @batch_ver: Incremented for each batch of config packets
* @global_inst: Instance allocator for groups
* @rst_cfg: Marker to reset HW LAG config
* @retrans_skbs: Cmsgs that could not be processed by HW and require
* retransmission
*/
struct nfp_fl_lag {
struct notifier_block lag_nb;
Expand All @@ -120,6 +122,7 @@ struct nfp_fl_lag {
unsigned int batch_ver;
u8 global_inst;
bool rst_cfg;
struct sk_buff_head retrans_skbs;
};

/**
Expand Down Expand Up @@ -280,5 +283,6 @@ int nfp_flower_setup_tc_egress_cb(enum tc_setup_type type, void *type_data,
void nfp_flower_lag_init(struct nfp_fl_lag *lag);
void nfp_flower_lag_cleanup(struct nfp_fl_lag *lag);
int nfp_flower_lag_reset(struct nfp_fl_lag *lag);
bool nfp_flower_lag_unprocessed_msg(struct nfp_app *app, struct sk_buff *skb);

#endif

0 comments on commit 2e1cc52

Please sign in to comment.