1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
9 roc_npc_vtag_actions_get(struct roc_npc *roc_npc)
11 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
13 return npc->vtag_actions;
17 roc_npc_vtag_actions_sub_return(struct roc_npc *roc_npc, uint32_t count)
19 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
21 npc->vtag_actions -= count;
22 return npc->vtag_actions;
26 roc_npc_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id)
28 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
30 return npc_mcam_free_counter(npc, ctr_id);
34 roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id,
37 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
39 return npc_mcam_read_counter(npc, ctr_id, count);
43 roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id)
45 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
47 return npc_mcam_clear_counter(npc, ctr_id);
51 roc_npc_mcam_free_entry(struct roc_npc *roc_npc, uint32_t entry)
53 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
55 return npc_mcam_free_entry(npc, entry);
59 roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc)
61 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
63 return npc_flow_free_all_resources(npc);
67 roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry,
68 int *alloc_entry, int req_count, int priority,
71 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
73 return npc_mcam_alloc_entries(npc, ref_entry, alloc_entry, req_count,
74 priority, resp_count);
78 roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam,
79 struct roc_npc_flow *ref_mcam, int prio,
82 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
84 return npc_mcam_alloc_entry(npc, mcam, ref_mcam, prio, resp_count);
88 roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam,
91 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
93 return npc_mcam_ena_dis_entry(npc, mcam, enable);
97 roc_npc_mcam_write_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam)
99 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
101 return npc_mcam_write_entry(npc, mcam);
105 roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc)
107 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
109 if (roc_model_is_cn10k())
110 return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1);
112 return (npc->mcam_entries - NPC_MCAME_RESVD_9XXX - 1);
116 npc_mcam_tot_entries(void)
118 /* FIXME: change to reading in AF from NPC_AF_CONST1/2
119 * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS
121 if (roc_model_is_cn10k() || roc_model_is_cn98xx())
122 return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */
124 return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */
128 roc_npc_profile_name_get(struct roc_npc *roc_npc)
130 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
132 return (char *)npc->profile_name;
136 roc_npc_init(struct roc_npc *roc_npc)
138 uint8_t *mem = NULL, *nix_mem = NULL, *npc_mem = NULL;
139 struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix);
140 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
145 PLT_STATIC_ASSERT(sizeof(struct npc) <= ROC_NPC_MEM_SZ);
147 memset(npc, 0, sizeof(*npc));
148 npc->mbox = (&nix->dev)->mbox;
149 roc_npc->channel = nix->rx_chan_base;
150 roc_npc->pf_func = (&nix->dev)->pf_func;
151 npc->channel = roc_npc->channel;
152 npc->pf_func = roc_npc->pf_func;
153 npc->flow_max_priority = roc_npc->flow_max_priority;
154 npc->switch_header_type = roc_npc->switch_header_type;
155 npc->flow_prealloc_size = roc_npc->flow_prealloc_size;
157 if (npc->mbox == NULL)
158 return NPC_ERR_PARAM;
160 rc = npc_mcam_fetch_kex_cfg(npc);
164 roc_npc->kex_capability = npc_get_kex_capability(npc);
165 roc_npc->rx_parse_nibble = npc->keyx_supp_nmask[NPC_MCAM_RX];
167 npc->mark_actions = 0;
169 npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX];
171 /* Free, free_rev, live and live_rev entries */
172 bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries);
173 mem = plt_zmalloc(4 * bmap_sz * npc->flow_max_priority, 0);
175 plt_err("Bmap alloc failed");
180 sz = npc->flow_max_priority * sizeof(struct npc_mcam_ents_info);
181 npc->flow_entry_info = plt_zmalloc(sz, 0);
182 if (npc->flow_entry_info == NULL) {
183 plt_err("flow_entry_info alloc failed");
188 sz = npc->flow_max_priority * sizeof(struct plt_bitmap *);
189 npc->free_entries = plt_zmalloc(sz, 0);
190 if (npc->free_entries == NULL) {
191 plt_err("free_entries alloc failed");
196 sz = npc->flow_max_priority * sizeof(struct plt_bitmap *);
197 npc->free_entries_rev = plt_zmalloc(sz, 0);
198 if (npc->free_entries_rev == NULL) {
199 plt_err("free_entries_rev alloc failed");
204 sz = npc->flow_max_priority * sizeof(struct plt_bitmap *);
205 npc->live_entries = plt_zmalloc(sz, 0);
206 if (npc->live_entries == NULL) {
207 plt_err("live_entries alloc failed");
212 sz = npc->flow_max_priority * sizeof(struct plt_bitmap *);
213 npc->live_entries_rev = plt_zmalloc(sz, 0);
214 if (npc->live_entries_rev == NULL) {
215 plt_err("live_entries_rev alloc failed");
220 sz = npc->flow_max_priority * sizeof(struct npc_flow_list);
221 npc->flow_list = plt_zmalloc(sz, 0);
222 if (npc->flow_list == NULL) {
223 plt_err("flow_list alloc failed");
229 for (idx = 0; idx < npc->flow_max_priority; idx++) {
230 TAILQ_INIT(&npc->flow_list[idx]);
232 npc->free_entries[idx] =
233 plt_bitmap_init(npc->mcam_entries, mem, bmap_sz);
236 npc->free_entries_rev[idx] =
237 plt_bitmap_init(npc->mcam_entries, mem, bmap_sz);
240 npc->live_entries[idx] =
241 plt_bitmap_init(npc->mcam_entries, mem, bmap_sz);
244 npc->live_entries_rev[idx] =
245 plt_bitmap_init(npc->mcam_entries, mem, bmap_sz);
248 npc->flow_entry_info[idx].free_ent = 0;
249 npc->flow_entry_info[idx].live_ent = 0;
250 npc->flow_entry_info[idx].max_id = 0;
251 npc->flow_entry_info[idx].min_id = ~(0);
254 npc->rss_grps = NPC_RSS_GRPS;
256 bmap_sz = plt_bitmap_get_memory_footprint(npc->rss_grps);
257 nix_mem = plt_zmalloc(bmap_sz, 0);
258 if (nix_mem == NULL) {
259 plt_err("Bmap alloc failed");
264 npc->rss_grp_entries = plt_bitmap_init(npc->rss_grps, nix_mem, bmap_sz);
266 if (!npc->rss_grp_entries) {
267 plt_err("bitmap init failed");
272 /* Group 0 will be used for RSS,
273 * 1 -7 will be used for npc_flow RSS action
275 plt_bitmap_set(npc->rss_grp_entries, 0);
281 plt_free(npc->flow_list);
282 if (npc->live_entries_rev)
283 plt_free(npc->live_entries_rev);
284 if (npc->live_entries)
285 plt_free(npc->live_entries);
286 if (npc->free_entries_rev)
287 plt_free(npc->free_entries_rev);
288 if (npc->free_entries)
289 plt_free(npc->free_entries);
290 if (npc->flow_entry_info)
291 plt_free(npc->flow_entry_info);
298 roc_npc_fini(struct roc_npc *roc_npc)
300 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
303 rc = npc_flow_free_all_resources(npc);
305 plt_err("Error when deleting NPC MCAM entries, counters");
309 if (npc->flow_list) {
310 plt_free(npc->flow_list);
311 npc->flow_list = NULL;
314 if (npc->live_entries_rev) {
315 plt_free(npc->live_entries_rev);
316 npc->live_entries_rev = NULL;
319 if (npc->live_entries) {
320 plt_free(npc->live_entries);
321 npc->live_entries = NULL;
324 if (npc->free_entries_rev) {
325 plt_free(npc->free_entries_rev);
326 npc->free_entries_rev = NULL;
329 if (npc->free_entries) {
330 plt_free(npc->free_entries);
331 npc->free_entries = NULL;
334 if (npc->flow_entry_info) {
335 plt_free(npc->flow_entry_info);
336 npc->flow_entry_info = NULL;
343 npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr,
344 const struct roc_npc_action actions[],
345 struct roc_npc_flow *flow)
347 const struct roc_npc_action_mark *act_mark;
348 const struct roc_npc_action_queue *act_q;
349 const struct roc_npc_action_vf *vf_act;
350 bool vlan_insert_action = false;
351 int sel_act, req_act = 0;
352 uint16_t pf_func, vf_id;
357 /* Initialize actions */
358 flow->ctr_id = NPC_COUNTER_NONE;
359 pf_func = npc->pf_func;
361 for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
362 switch (actions->type) {
363 case ROC_NPC_ACTION_TYPE_VOID:
365 case ROC_NPC_ACTION_TYPE_MARK:
366 act_mark = (const struct roc_npc_action_mark *)
368 if (act_mark->id > (NPC_FLOW_FLAG_VAL - 2)) {
369 plt_err("mark value must be < 0xfffe");
372 mark = act_mark->id + 1;
373 req_act |= ROC_NPC_ACTION_TYPE_MARK;
374 npc->mark_actions += 1;
377 case ROC_NPC_ACTION_TYPE_FLAG:
378 mark = NPC_FLOW_FLAG_VAL;
379 req_act |= ROC_NPC_ACTION_TYPE_FLAG;
380 npc->mark_actions += 1;
383 case ROC_NPC_ACTION_TYPE_COUNT:
384 /* Indicates, need a counter */
386 req_act |= ROC_NPC_ACTION_TYPE_COUNT;
389 case ROC_NPC_ACTION_TYPE_DROP:
390 req_act |= ROC_NPC_ACTION_TYPE_DROP;
393 case ROC_NPC_ACTION_TYPE_PF:
394 req_act |= ROC_NPC_ACTION_TYPE_PF;
398 case ROC_NPC_ACTION_TYPE_VF:
400 (const struct roc_npc_action_vf *)actions->conf;
401 req_act |= ROC_NPC_ACTION_TYPE_VF;
402 vf_id = vf_act->id & RVU_PFVF_FUNC_MASK;
404 pf_func = (pf_func | (vf_id + 1));
407 case ROC_NPC_ACTION_TYPE_QUEUE:
408 act_q = (const struct roc_npc_action_queue *)
411 req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
414 case ROC_NPC_ACTION_TYPE_RSS:
415 req_act |= ROC_NPC_ACTION_TYPE_RSS;
418 case ROC_NPC_ACTION_TYPE_SEC:
419 /* Assumes user has already configured security
420 * session for this flow. Associated conf is
421 * opaque. When security is implemented,
422 * we need to verify that for specified security
425 * NPC_SECURITY_ACTION_TYPE_INLINE_PROTOCOL &&
426 * session_protocol ==
427 * NPC_SECURITY_PROTOCOL_IPSEC
429 * RSS is not supported with inline ipsec. Get the
430 * rq from associated conf, or make
431 * ROC_NPC_ACTION_TYPE_QUEUE compulsory with this
433 * Currently, rq = 0 is assumed.
435 req_act |= ROC_NPC_ACTION_TYPE_SEC;
438 case ROC_NPC_ACTION_TYPE_VLAN_STRIP:
439 req_act |= ROC_NPC_ACTION_TYPE_VLAN_STRIP;
441 case ROC_NPC_ACTION_TYPE_VLAN_INSERT:
442 req_act |= ROC_NPC_ACTION_TYPE_VLAN_INSERT;
444 case ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT:
445 req_act |= ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
447 case ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT:
448 req_act |= ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
451 errcode = NPC_ERR_ACTION_NOTSUP;
456 if (req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT |
457 ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
458 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT))
459 vlan_insert_action = true;
461 if ((req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT |
462 ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
463 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT)) ==
464 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
465 plt_err("PCP insert action can't be supported alone");
466 errcode = NPC_ERR_ACTION_NOTSUP;
470 /* Both STRIP and INSERT actions are not supported */
471 if (vlan_insert_action && (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)) {
472 errcode = NPC_ERR_ACTION_NOTSUP;
476 /* Check if actions specified are compatible */
478 if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
479 plt_err("VLAN pop action is not supported on Egress");
480 errcode = NPC_ERR_ACTION_NOTSUP;
484 if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
485 flow->npc_action = NIX_TX_ACTIONOP_DROP;
486 } else if ((req_act & ROC_NPC_ACTION_TYPE_COUNT) ||
487 vlan_insert_action) {
488 flow->npc_action = NIX_TX_ACTIONOP_UCAST_DEFAULT;
490 plt_err("Unsupported action for egress");
491 errcode = NPC_ERR_ACTION_NOTSUP;
497 if (vlan_insert_action) {
498 errcode = NPC_ERR_ACTION_NOTSUP;
503 /* We have already verified the attr, this is ingress.
504 * - Exactly one terminating action is supported
505 * - Exactly one of MARK or FLAG is supported
506 * - If terminating action is DROP, only count is valid.
508 sel_act = req_act & NPC_ACTION_TERM;
509 if ((sel_act & (sel_act - 1)) != 0) {
510 errcode = NPC_ERR_ACTION_NOTSUP;
514 if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
515 sel_act = req_act & ~ROC_NPC_ACTION_TYPE_COUNT;
516 if ((sel_act & (sel_act - 1)) != 0) {
517 errcode = NPC_ERR_ACTION_NOTSUP;
522 if ((req_act & (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) ==
523 (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) {
524 errcode = NPC_ERR_ACTION_NOTSUP;
528 if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)
531 /* Only VLAN action is provided */
532 if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP)
533 flow->npc_action = NIX_RX_ACTIONOP_UCAST;
535 /* Set NIX_RX_ACTIONOP */
536 if (req_act & (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) {
537 flow->npc_action = NIX_RX_ACTIONOP_UCAST;
538 if (req_act & ROC_NPC_ACTION_TYPE_QUEUE)
539 flow->npc_action |= (uint64_t)rq << 20;
540 } else if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
541 flow->npc_action = NIX_RX_ACTIONOP_DROP;
542 } else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
543 flow->npc_action = NIX_RX_ACTIONOP_UCAST;
544 flow->npc_action |= (uint64_t)rq << 20;
545 } else if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
546 flow->npc_action = NIX_RX_ACTIONOP_UCAST;
547 } else if (req_act & ROC_NPC_ACTION_TYPE_SEC) {
548 flow->npc_action = NIX_RX_ACTIONOP_UCAST_IPSEC;
549 flow->npc_action |= (uint64_t)rq << 20;
551 (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) {
552 flow->npc_action = NIX_RX_ACTIONOP_UCAST;
553 } else if (req_act & ROC_NPC_ACTION_TYPE_COUNT) {
554 /* Keep ROC_NPC_ACTION_TYPE_COUNT_ACT always at the end
555 * This is default action, when user specify only
558 flow->npc_action = NIX_RX_ACTIONOP_UCAST;
560 /* Should never reach here */
561 errcode = NPC_ERR_ACTION_NOTSUP;
566 flow->npc_action |= (uint64_t)mark << 40;
569 /* Ideally AF must ensure that correct pf_func is set */
570 flow->npc_action |= (uint64_t)pf_func << 4;
578 typedef int (*npc_parse_stage_func_t)(struct npc_parse_state *pst);
581 npc_parse_pattern(struct npc *npc, const struct roc_npc_item_info pattern[],
582 struct roc_npc_flow *flow, struct npc_parse_state *pst)
584 npc_parse_stage_func_t parse_stage_funcs[] = {
585 npc_parse_meta_items, npc_parse_cpt_hdr, npc_parse_higig2_hdr,
586 npc_parse_la, npc_parse_lb, npc_parse_lc,
587 npc_parse_ld, npc_parse_le, npc_parse_lf,
588 npc_parse_lg, npc_parse_lh,
595 return NPC_ERR_PARAM;
597 memset(pst, 0, sizeof(*pst));
601 /* Use integral byte offset */
602 key_offset = pst->npc->keyx_len[flow->nix_intf];
603 key_offset = (key_offset + 7) / 8;
605 /* Location where LDATA would begin */
606 pst->mcam_data = (uint8_t *)flow->mcam_data;
607 pst->mcam_mask = (uint8_t *)flow->mcam_mask;
609 while (pattern->type != ROC_NPC_ITEM_TYPE_END &&
610 layer < PLT_DIM(parse_stage_funcs)) {
611 /* Skip place-holders */
612 pattern = npc_parse_skip_void_and_any_items(pattern);
614 pst->pattern = pattern;
615 rc = parse_stage_funcs[layer](pst);
622 * Parse stage function sets pst->pattern to
623 * 1 past the last item it consumed.
625 pattern = pst->pattern;
631 /* Skip trailing place-holders */
632 pattern = npc_parse_skip_void_and_any_items(pattern);
634 /* Are there more items than what we can handle? */
635 if (pattern->type != ROC_NPC_ITEM_TYPE_END)
636 return NPC_ERR_PATTERN_NOTSUP;
642 npc_parse_attr(struct npc *npc, const struct roc_npc_attr *attr,
643 struct roc_npc_flow *flow)
646 return NPC_ERR_PARAM;
647 else if (attr->priority >= npc->flow_max_priority)
648 return NPC_ERR_PARAM;
649 else if ((!attr->egress && !attr->ingress) ||
650 (attr->egress && attr->ingress))
651 return NPC_ERR_PARAM;
654 flow->nix_intf = ROC_NPC_INTF_RX;
656 flow->nix_intf = ROC_NPC_INTF_TX;
658 flow->priority = attr->priority;
663 npc_parse_rule(struct npc *npc, const struct roc_npc_attr *attr,
664 const struct roc_npc_item_info pattern[],
665 const struct roc_npc_action actions[], struct roc_npc_flow *flow,
666 struct npc_parse_state *pst)
671 err = npc_parse_attr(npc, attr, flow);
676 err = npc_parse_pattern(npc, pattern, flow, pst);
681 err = npc_parse_actions(npc, attr, actions, flow);
688 roc_npc_flow_parse(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
689 const struct roc_npc_item_info pattern[],
690 const struct roc_npc_action actions[],
691 struct roc_npc_flow *flow)
693 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
694 struct npc_parse_state parse_state = {0};
697 rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state);
701 parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix);
703 return npc_program_mcam(npc, &parse_state, 0);
707 npc_rss_free_grp_get(struct npc *npc, uint32_t *pos)
709 struct plt_bitmap *bmap = npc->rss_grp_entries;
711 for (*pos = 0; *pos < ROC_NIX_RSS_GRPS; ++*pos) {
712 if (!plt_bitmap_get(bmap, *pos))
715 return *pos < ROC_NIX_RSS_GRPS ? 0 : -1;
719 npc_rss_action_configure(struct roc_npc *roc_npc,
720 const struct roc_npc_action_rss *rss, uint8_t *alg_idx,
721 uint32_t *rss_grp, uint32_t mcam_id)
723 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
724 struct roc_nix *roc_nix = roc_npc->roc_nix;
725 struct nix *nix = roc_nix_to_nix_priv(roc_nix);
726 uint32_t flowkey_cfg, rss_grp_idx, i, rem;
727 uint8_t key[ROC_NIX_RSS_KEY_LEN];
728 const uint8_t *key_ptr;
729 uint8_t flowkey_algx;
733 rc = npc_rss_free_grp_get(npc, &rss_grp_idx);
734 /* RSS group :0 is not usable for flow rss action */
735 if (rc < 0 || rss_grp_idx == 0)
738 for (i = 0; i < rss->queue_num; i++) {
739 if (rss->queue[i] >= nix->nb_rx_queues) {
740 plt_err("queue id > max number of queues");
745 *rss_grp = rss_grp_idx;
747 if (rss->key == NULL) {
748 roc_nix_rss_key_default_fill(roc_nix, key);
754 roc_nix_rss_key_set(roc_nix, key_ptr);
756 /* If queue count passed in the rss action is less than
757 * HW configured reta size, replicate rss action reta
758 * across HW reta table.
760 reta = nix->reta[rss_grp_idx];
762 if (rss->queue_num > nix->reta_sz) {
763 plt_err("too many queues for RSS context");
767 for (i = 0; i < (nix->reta_sz / rss->queue_num); i++)
768 memcpy(reta + i * rss->queue_num, rss->queue,
769 sizeof(uint16_t) * rss->queue_num);
771 rem = nix->reta_sz % rss->queue_num;
773 memcpy(&reta[i * rss->queue_num], rss->queue,
774 rem * sizeof(uint16_t));
776 rc = roc_nix_rss_reta_set(roc_nix, *rss_grp, reta);
778 plt_err("Failed to init rss table rc = %d", rc);
782 flowkey_cfg = roc_npc->flowkey_cfg_state;
784 rc = roc_nix_rss_flowkey_set(roc_nix, &flowkey_algx, flowkey_cfg,
787 plt_err("Failed to set rss hash function rc = %d", rc);
791 *alg_idx = flowkey_algx;
793 plt_bitmap_set(npc->rss_grp_entries, *rss_grp);
799 npc_rss_action_program(struct roc_npc *roc_npc,
800 const struct roc_npc_action actions[],
801 struct roc_npc_flow *flow)
803 const struct roc_npc_action_rss *rss;
808 for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
809 if (actions->type == ROC_NPC_ACTION_TYPE_RSS) {
810 rss = (const struct roc_npc_action_rss *)actions->conf;
811 rc = npc_rss_action_configure(roc_npc, rss, &alg_idx,
812 &rss_grp, flow->mcam_id);
816 flow->npc_action &= (~(0xfULL));
817 flow->npc_action |= NIX_RX_ACTIONOP_RSS;
819 ((uint64_t)(alg_idx & NPC_RSS_ACT_ALG_MASK)
820 << NPC_RSS_ACT_ALG_OFFSET) |
821 ((uint64_t)(rss_grp & NPC_RSS_ACT_GRP_MASK)
822 << NPC_RSS_ACT_GRP_OFFSET);
830 roc_npc_mark_actions_get(struct roc_npc *roc_npc)
832 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
834 return npc->mark_actions;
838 roc_npc_mark_actions_sub_return(struct roc_npc *roc_npc, uint32_t count)
840 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
842 npc->mark_actions -= count;
843 return npc->mark_actions;
847 npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
849 struct roc_nix *roc_nix = roc_npc->roc_nix;
850 struct nix_vtag_config *vtag_cfg;
851 struct nix_vtag_config_rsp *rsp;
858 struct nix_tx_vtag_action_s act;
861 nix = roc_nix_to_nix_priv(roc_nix);
862 mbox = (&nix->dev)->mbox;
864 tx_vtag_action.reg = flow->vtag_action;
865 vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
867 if (vtag_cfg == NULL)
870 vtag_cfg->cfg_type = VTAG_TX;
871 vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
872 vtag_cfg->tx.vtag0_idx = tx_vtag_action.act.vtag0_def;
873 vtag_cfg->tx.free_vtag0 = true;
875 rc = mbox_process_msg(mbox, (void *)&rsp);
883 npc_vtag_action_program(struct roc_npc *roc_npc,
884 const struct roc_npc_action actions[],
885 struct roc_npc_flow *flow)
887 uint16_t vlan_id = 0, vlan_ethtype = ROC_ETHER_TYPE_VLAN;
888 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
889 struct roc_nix *roc_nix = roc_npc->roc_nix;
890 struct nix_vtag_config *vtag_cfg;
891 struct nix_vtag_config_rsp *rsp;
892 uint64_t rx_vtag_action = 0;
893 uint8_t vlan_pcp = 0;
900 struct nix_tx_vtag_action_s act;
903 nix = roc_nix_to_nix_priv(roc_nix);
904 mbox = (&nix->dev)->mbox;
906 flow->vtag_insert_enabled = false;
908 for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
909 if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
910 if (npc->vtag_actions == 1) {
911 vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
913 if (vtag_cfg == NULL)
916 vtag_cfg->cfg_type = VTAG_RX;
917 vtag_cfg->rx.strip_vtag = 1;
919 vtag_cfg->rx.capture_vtag = 1;
920 vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
921 vtag_cfg->rx.vtag_type = 0;
923 rc = mbox_process(mbox);
928 rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15);
929 rx_vtag_action |= ((uint64_t)NPC_LID_LB << 8);
930 rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR;
931 flow->vtag_action = rx_vtag_action;
932 } else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) {
933 const struct roc_npc_action_of_set_vlan_vid *vtag =
934 (const struct roc_npc_action_of_set_vlan_vid *)
936 vlan_id = plt_be_to_cpu_16(vtag->vlan_vid);
937 if (vlan_id > 0xfff) {
938 plt_err("Invalid vlan_id for set vlan action");
941 flow->vtag_insert_enabled = true;
942 } else if (actions->type ==
943 ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT) {
944 const struct roc_npc_action_of_push_vlan *ethtype =
945 (const struct roc_npc_action_of_push_vlan *)
947 vlan_ethtype = plt_be_to_cpu_16(ethtype->ethertype);
948 if (vlan_ethtype != ROC_ETHER_TYPE_VLAN &&
949 vlan_ethtype != ROC_ETHER_TYPE_QINQ) {
950 plt_err("Invalid ethtype specified for push"
954 flow->vtag_insert_enabled = true;
955 } else if (actions->type ==
956 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
957 const struct roc_npc_action_of_set_vlan_pcp *pcp =
958 (const struct roc_npc_action_of_set_vlan_pcp *)
960 vlan_pcp = pcp->vlan_pcp;
961 if (vlan_pcp > 0x7) {
962 plt_err("Invalid PCP value for pcp action");
965 flow->vtag_insert_enabled = true;
969 if (flow->vtag_insert_enabled) {
970 vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
972 if (vtag_cfg == NULL)
975 vtag_cfg->cfg_type = VTAG_TX;
976 vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
978 ((vlan_ethtype << 16) | (vlan_pcp << 13) | vlan_id);
980 vtag_cfg->tx.cfg_vtag0 = 1;
981 rc = mbox_process_msg(mbox, (void *)&rsp);
985 if (rsp->vtag0_idx < 0) {
986 plt_err("Failed to config TX VTAG action");
990 tx_vtag_action.reg = 0;
991 tx_vtag_action.act.vtag0_def = rsp->vtag0_idx;
992 tx_vtag_action.act.vtag0_lid = NPC_LID_LA;
993 tx_vtag_action.act.vtag0_op = NIX_TX_VTAGOP_INSERT;
994 tx_vtag_action.act.vtag0_relptr =
995 NIX_TX_VTAGACTION_VTAG0_RELPTR;
996 flow->vtag_action = tx_vtag_action.reg;
1001 struct roc_npc_flow *
1002 roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
1003 const struct roc_npc_item_info pattern[],
1004 const struct roc_npc_action actions[], int *errcode)
1006 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1007 struct roc_npc_flow *flow, *flow_iter;
1008 struct npc_parse_state parse_state;
1009 struct npc_flow_list *list;
1012 flow = plt_zmalloc(sizeof(*flow), 0);
1014 *errcode = NPC_ERR_NO_MEM;
1017 memset(flow, 0, sizeof(*flow));
1019 rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state);
1025 rc = npc_vtag_action_program(roc_npc, actions, flow);
1031 parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix);
1033 rc = npc_program_mcam(npc, &parse_state, 1);
1039 rc = npc_rss_action_program(roc_npc, actions, flow);
1042 goto set_rss_failed;
1045 list = &npc->flow_list[flow->priority];
1046 /* List in ascending order of mcam entries */
1047 TAILQ_FOREACH(flow_iter, list, next) {
1048 if (flow_iter->mcam_id > flow->mcam_id) {
1049 TAILQ_INSERT_BEFORE(flow_iter, flow, next);
1054 TAILQ_INSERT_TAIL(list, flow, next);
1058 rc = npc_mcam_free_entry(npc, flow->mcam_id);
1070 npc_rss_group_free(struct npc *npc, struct roc_npc_flow *flow)
1074 if ((flow->npc_action & 0xF) == NIX_RX_ACTIONOP_RSS) {
1075 rss_grp = (flow->npc_action >> NPC_RSS_ACT_GRP_OFFSET) &
1076 NPC_RSS_ACT_GRP_MASK;
1077 if (rss_grp == 0 || rss_grp >= npc->rss_grps)
1080 plt_bitmap_clear(npc->rss_grp_entries, rss_grp);
1087 roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
1089 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1090 struct plt_bitmap *bmap;
1093 rc = npc_rss_group_free(npc, flow);
1095 plt_err("Failed to free rss action rc = %d", rc);
1099 if (flow->vtag_insert_enabled) {
1100 rc = npc_vtag_cfg_delete(roc_npc, flow);
1105 rc = npc_mcam_free_entry(npc, flow->mcam_id);
1109 TAILQ_REMOVE(&npc->flow_list[flow->priority], flow, next);
1111 bmap = npc->live_entries[flow->priority];
1112 plt_bitmap_clear(bmap, flow->mcam_id);
1119 roc_npc_flow_dump(FILE *file, struct roc_npc *roc_npc)
1121 struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1122 struct roc_npc_flow *flow_iter;
1123 struct npc_flow_list *list;
1124 uint32_t max_prio, i;
1126 max_prio = npc->flow_max_priority;
1128 for (i = 0; i < max_prio; i++) {
1129 list = &npc->flow_list[i];
1131 /* List in ascending order of mcam entries */
1132 TAILQ_FOREACH(flow_iter, list, next) {
1133 roc_npc_flow_mcam_dump(file, roc_npc, flow_iter);