blob: acb85d312ac071812d8a1f77992d2d49c08761b7 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/******************************************************************************
2 *
3 * <:copyright-BRCM:2016:DUAL/GPL:standard
4 *
5 * Copyright (c) 2016 Broadcom
6 * All Rights Reserved
7 *
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed
10 * to you under the terms of the GNU General Public License version 2
11 * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
12 * with the following added to such license:
13 *
14 * As a special exception, the copyright holders of this software give
15 * you permission to link this software with independent modules, and
16 * to copy and distribute the resulting executable under terms of your
17 * choice, provided that you also meet, for each linked independent
18 * module, the terms and conditions of the license of that module.
19 * An independent module is a module which is not derived from this
20 * software. The special exception does not apply to any modifications
21 * of the software.
22 *
23 * Not withstanding the above, under no circumstances may you combine
24 * this software in any way with any other Broadcom software provided
25 * under a license other than the GPL, without Broadcom's express prior
26 * written consent.
27 *
28 * :>
29 *
30 *****************************************************************************/
31
32/**
33 * @file bal_switch_flow.c
34 * @brief BAL Switch util functions that handle flow requests
35 * @addtogroup sw_util
36 */
37
38 /*@{*/
39#include <bal_common.h>
40#include <bcm_dev_log.h>
41#include <bal_msg.h>
42#include "bal_switch_flow.h"
43#include "flow_fsm.h"
44#include "bcmos_errno.h"
45#include "bal_switch_util.h"
46
47#ifndef TEST_SW_UTIL_LOOPBACK
48#include <bcm/types.h>
49#include <sal/core/libc.h>
50#ifndef sal_memset
51#define sal_memset memset
52#endif
53#include <bcm/port.h>
54#include <bcm/vlan.h>
55#include <bcm/field.h>
56#include <bcm/error.h>
57#include <sal/core/libc.h>
58
59#include "bal_switch_acc_term.h"
60#include "esw/bal_esw_flow.h"
61#include "dpp/bal_dpp_flow.h"
62#include "dpp/bal_dpp_vswitch.h"
63
64#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
65
66/* A golbal link list to keep track of flows in the switch */
67TAILQ_HEAD(bal_sw_flow_list_head, bal_sw_flow) g_swutil_flow_list;
68
69static void sw_util_flow_dump_classifier(bcmbal_flow_cfg *p_flow)
70{
71 char dst_ip_str[16];
72
73 bcmos_inet_ntoa(&p_flow->data.classifier.dst_ip, dst_ip_str);
74
75 /* Do not use normal BCM_LOG() (but BCM_LOG_CALLER_FMT()), as IP address is a stack variable. */
76 BCM_LOG_CALLER_FMT(DEBUG, log_id_sw_util,
77 " classifier - otpid=0x%x itpid=0x%x ovid=0x%x ivid=0x%x opcp=0x%x, ipcp=0x%x "
78 "ether_type=0x%x dst_mac=%02x:%02x:%02x:%02x:%02x:%02x ip_proto=0x%x dst_ip=%s src_port=%u dst_port=%u attr_mask=0x%x\n",
79 p_flow->data.classifier.o_tpid, p_flow->data.classifier.i_tpid,
80 p_flow->data.classifier.o_vid, p_flow->data.classifier.i_vid,
81 p_flow->data.classifier.o_pbits,
82 p_flow->data.classifier.i_pbits,
83 p_flow->data.classifier.ether_type,
84 p_flow->data.classifier.dst_mac.u8[0], p_flow->data.classifier.dst_mac.u8[1], p_flow->data.classifier.dst_mac.u8[2],
85 p_flow->data.classifier.dst_mac.u8[3], p_flow->data.classifier.dst_mac.u8[4], p_flow->data.classifier.dst_mac.u8[5],
86 p_flow->data.classifier.ip_proto,
87 dst_ip_str,
88 p_flow->data.classifier.src_port,
89 p_flow->data.classifier.dst_port,
90 (unsigned int)p_flow->data.classifier.presence_mask);
91}
92
93static void sw_util_flow_dump_sla(bcmbal_flow_cfg *p_flow)
94{
95 BCM_LOG(DEBUG, log_id_sw_util, " sla - min_rate=%u max_rate=%u attr_mask=0x%x\n",
96 p_flow->data.sla.min_rate,
97 p_flow->data.sla.max_rate,
98 (unsigned int)p_flow->data.sla.presence_mask);
99}
100
101#define OUTER_VLAN_TAG_REQ_BITMASK (BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG | \
102 BCMBAL_ACTION_CMD_ID_XLATE_OUTER_TAG | \
103 BCMBAL_ACTION_CMD_ID_XLATE_TWO_TAGS | \
104 BCMBAL_ACTION_CMD_ID_REMOVE_TWO_TAGS | \
105 BCMBAL_ACTION_CMD_ID_REMARK_PBITS | \
106 BCMBAL_ACTION_CMD_ID_COPY_PBITS | \
107 BCMBAL_ACTION_CMD_ID_REVERSE_COPY_PBITS | \
108 BCMBAL_ACTION_CMD_ID_DSCP_TO_PBITS)
109
110#define NOT_WORKING_ACTION_BITMASK (BCMBAL_ACTION_CMD_ID_ADD_TWO_TAGS | \
111 BCMBAL_ACTION_CMD_ID_REMOVE_TWO_TAGS | \
112 BCMBAL_ACTION_CMD_ID_XLATE_TWO_TAGS | \
113 BCMBAL_ACTION_CMD_ID_DISCARD_DS_BCAST | \
114 BCMBAL_ACTION_CMD_ID_DISCARD_DS_UNKNOWN | \
115 BCMBAL_ACTION_CMD_ID_COPY_PBITS | \
116 BCMBAL_ACTION_CMD_ID_REVERSE_COPY_PBITS | \
117 BCMBAL_ACTION_CMD_ID_DSCP_TO_PBITS)
118
119/**
120 * @brief The flow check function validate the flow parameters from the core
121 *
122 * @param p_msg A pointer to the flow object to validate
123 * @return error code
124 */
125bcmos_errno sw_util_flow_info_validate(void *p_msg)
126{
127 bcmbal_flow_cfg *p_flow = (bcmbal_flow_cfg *)p_msg;
128 bcmos_errno ret = BCM_ERR_OK;
129
130 if (p_flow == NULL)
131 {
132 BCM_LOG(ERROR, log_id_sw_util,
133 " No flow specified during validation\n" );
134 return BCM_ERR_PARM;
135 }
136 else
137 {
138 BCM_LOG(INFO, log_id_sw_util,
139 " Got a flow request - flow_id=%d sub_port=%d svc_id=%d, attr_mask=0x%x\n",
140 p_flow->key.flow_id, p_flow->data.access_int_id,
141 p_flow->data.svc_port_id, (unsigned int)p_flow->hdr.hdr.presence_mask);
142
143 sw_util_flow_dump_classifier(p_flow);
144 if (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM)
145 sw_util_flow_dump_sla(p_flow);
146 }
147
148 /* validate the NNI range */
149 if((BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, network_int_id)) &&
150 (BCMOS_FALSE == bcm_topo_nni_is_valid(p_flow->data.network_int_id )) )
151 {
152 uint32_t max_nni_ports = 0;
153
154#ifndef TEST_SW_UTIL_LOOPBACK
155 bcm_topo_dev_get_max_nni(bal_bcm_net_inf_dev_get(p_flow->data.network_int_id), &max_nni_ports);
156#else
157 bcm_topo_dev_get_max_nni(0, &max_nni_ports);
158#endif
159 BCM_LOG(ERROR, log_id_sw_util,
160 " Request network interface %d is out of max range %d\n",p_flow->data.network_int_id, max_nni_ports );
161 return BCM_ERR_PARM;
162 }
163
164 /* return BCM_ERR_NOT_SUPPORTED for actions that has not yet implemented */
165 if((BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action)) &&
166 (p_flow->data.action.cmds_bitmask & NOT_WORKING_ACTION_BITMASK))
167 {
168 BCM_LOG(ERROR, log_id_sw_util,
169 " Request Action Command 0x%x not supported yet\n",p_flow->data.action.cmds_bitmask );
170 return BCM_ERR_NOT_SUPPORTED;
171 }
172
173 if(BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, classifier))
174 {
175 BCM_LOG(ERROR, log_id_sw_util,
176 " a classifier must be specified in a flow\n" );
177 ret = BCM_ERR_PARM;
178 }
179 else
180 {
181 /* ING SDK allows priority range from 0x7fffffff to 0 */
182 /* Need to check the configuration range if unit32_t is used for the attribute */
183
184 /* An outer vid is required in the classifier for all actions that operate on the outer vlan tag */
185 if(BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid) &&
186 ((BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action)) &&
187 (p_flow->data.action.cmds_bitmask & OUTER_VLAN_TAG_REQ_BITMASK)))
188 {
189 BCM_LOG(ERROR, log_id_sw_util,
190 " o_vid must be specified when actions requiring an outer vlan tag is specified\n" );
191 ret = BCM_ERR_PARM;
192 }
193
194 /*An outer vid must be specified when an inner vid is specified */
195 if((BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid)) &&
196 (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_vid)))
197 {
198 BCM_LOG(ERROR, log_id_sw_util,
199 " o_vid must be specified when i_vid is specified\n" );
200 ret = BCM_ERR_PARM;
201 }
202
203 /* Check that user has specified pbits when the action is pbit remarking */
204 if((BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action)) &&
205 (p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_REMARK_PBITS) )
206 {
207 if((BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid)) ||
208 (BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.action, action, o_pbits)) )
209 {
210
211 BCM_LOG(ERROR, log_id_sw_util,
212 " o_vid in classifier and o_pibts in action must be specified when outer pbit remarking is specified\n" );
213 ret = BCM_ERR_PARM;
214 }
215 }
216
217 /* Check that the user has specified a valid packet tag type given the o_vid and i_vid choices (if any)*/
218 if(((BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid)) ||
219 (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_vid))))
220 {
221 if((BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, pkt_tag_type)) ||
222 ((BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, pkt_tag_type)) &&
223 (BCMBAL_PKT_TAG_TYPE_UNTAGGED == p_flow->data.classifier.pkt_tag_type)))
224 {
225 BCM_LOG(ERROR, log_id_sw_util,
226 " pkt_tag_type must be either SINGLE or DOUBLE tagged when o_vid or i_vid are specified\n" );
227 ret = BCM_ERR_PARM;
228 }
229 }
230 else
231 {
232 /* If the pkt_tag_type is not specified OR the pkt_tag_type is not UNTAGGED (and it's not destined
233 * to the host CPU), then it's an error
234 */
235 if(!(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action) &&
236 (p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)))
237 {
238 if(BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, pkt_tag_type) ||
239 (!(BCMBAL_PKT_TAG_TYPE_UNTAGGED == p_flow->data.classifier.pkt_tag_type)))
240 {
241 BCM_LOG(ERROR, log_id_sw_util,
242 " pkt_tag_type must be UNTAGGED when neither o_vid nor i_vid are specified\n" );
243 ret = BCM_ERR_PARM;
244 }
245 }
246 }
247
248 /* Now test the multicast flow cases */
249 if (BCMOS_TRUE == (BCMBAL_FLOW_TYPE_MULTICAST == p_flow->key.flow_type))
250 {
251 if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action) &&
252 (p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST))
253 {
254 BCM_LOG(ERROR, log_id_sw_util, " A multicast flow must not terminate in the host\n");
255 ret = BCM_ERR_PARM;
256 }
257
258 /* A Multicast flow must have a group_id that is valid (i.e. an active group) */
259 if(BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, group_id))
260 {
261 BCM_LOG(ERROR, log_id_sw_util, " A multicast flow must have a specified group_id\n");
262 ret = BCM_ERR_PARM;
263 }
264 else
265 {
266 /* Now check that the referenced group is valid */
267 bcmbal_group_key group_key = { .group_id = p_flow->data.group_id };
268 bcmbal_group_owner group_owner;
269
270 /* make sure the group owner is multicast */
271 if(BCM_ERR_OK == group_owner_get(group_key, &group_owner))
272 {
273 if ( BCMBAL_GROUP_OWNER_MULTICAST != group_owner)
274 {
275 BCM_LOG(ERROR, log_id_sw_util,
276 " A multicast flow must have group owner of type Multicast, group_id:%d\n",
277 group_key.group_id);
278 ret = BCM_ERR_PARM;
279 }
280 }
281 else
282 {
283 BCM_LOG(ERROR, log_id_sw_util,
284 " A multicast flow must have an valid group_id (Active group_id:%d not found)\n",
285 group_key.group_id);
286 ret = BCM_ERR_PARM;
287 }
288 }
289 }
290 /* check N:1 service Group Owner to be UNICAST */
291 if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, group_id) &&
292 (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow->key.flow_type ||
293 BCMBAL_FLOW_TYPE_UPSTREAM == p_flow->key.flow_type )
294 )
295 {
296 /* Now check that the referenced group is valid */
297 bcmbal_group_key group_key = { .group_id = p_flow->data.group_id };
298 bcmbal_group_owner group_owner;
299
300 /* make sure the group owner is unicast */
301 if(BCM_ERR_OK == group_owner_get(group_key, &group_owner))
302 {
303 if ( BCMBAL_GROUP_OWNER_UNICAST != group_owner)
304 {
305 BCM_LOG(ERROR, log_id_sw_util,
306 " A N:1 flow must have group owner of type unicast, group_id:%d\n",
307 group_key.group_id);
308 ret = BCM_ERR_PARM;
309 }
310 }
311 else
312 {
313 BCM_LOG(ERROR, log_id_sw_util,
314 " A N:1 flow must have an valid group_id (Active group_id:%d not found)\n",
315 group_key.group_id);
316 ret = BCM_ERR_PARM;
317 }
318 }
319 }
320
321 return ret;
322}
323
324/* Below local functions are used for real logic only */
325#ifndef TEST_SW_UTIL_LOOPBACK
326
327/**
328 * @brief The flow add function program the switch to forward packets that have
329 * specified attributes to the designated ports.
330 * The packets is modified before egress
331 * On the downstream, an access id (outer vlan tag) is added to the packets
332 * On the upstream, outer vlan tag (access id) is removed from the packets
333 *
334 * @param p_flow_inst A pointer to the flow instance being referenced
335 * @return error code
336 */
337static bcmos_errno bal_sw_util_flow_add(flow_inst *p_flow_inst)
338{
339 bcmbal_flow_cfg *p_flow = &p_flow_inst->api_req_flow_info;
340 bcmos_errno ret = BCM_ERR_OK;
341 int unit;
342 uint32_t dev_type;
343 bcmbal_iwf_mode iwf_mode;
344
345 BCM_LOG(INFO, log_id_sw_util,
346 " Got a flow request - flow_id=%d sub_port=%d svc_id=%d\n",
347 p_flow->key.flow_id, p_flow->data.access_int_id, p_flow->data.svc_port_id);
348
349 unit = bal_bcm_pon_inf_dev_get(p_flow->data.access_int_id);
350 dev_type = bal_bcm_dev_type_get(unit);
351 iwf_mode = bal_bcm_iwf_mode_get();
352
353 /* call the flow add function based on device type */
354 if (dev_type == BCM_DEVICE_KT2)
355 {
356 ret = bal_sw_util_esw_flow_add(iwf_mode, p_flow);
357 }
358 else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
359 {
360 ret = bal_sw_util_dpp_flow_add(iwf_mode, p_flow);
361 }
362 else
363 {
364 BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on flow add: 0x%x\n", dev_type );
365 ret = BCM_ERR_INTERNAL;
366 }
367
368 BCM_LOG(INFO, log_id_sw_util, " Return flow add request with %d on device 0x%x\n", ret, dev_type );
369
370 return ret;
371}
372
373/**
374 * @brief The flow remove function program switch to release resource that have
375 * been allocated during the flow add operation.
376 *
377 * @param p_flow_inst A pointer to the flow instance being referenced
378 * @return error code
379 */
380static bcmos_errno bal_sw_util_flow_remove(flow_inst *p_flow_inst)
381{
382 bcmbal_flow_cfg *p_flow = &p_flow_inst->api_req_flow_info;
383 bcmos_errno ret = BCM_ERR_OK;
384 int unit;
385 uint32_t dev_type;
386 bcmbal_iwf_mode iwf_mode;
387
388 BCM_LOG(INFO, log_id_sw_util,
389 " Got a flow remove request - flow_id=%d sub_port=%d svc_id=%d\n",
390 p_flow->key.flow_id, p_flow->data.access_int_id, p_flow->data.svc_port_id);
391
392 unit = bal_bcm_pon_inf_dev_get(p_flow->data.access_int_id);
393 dev_type = bal_bcm_dev_type_get(unit);
394 iwf_mode = bal_bcm_iwf_mode_get();
395
396 /* call the flow add function based on device type */
397 if (dev_type == BCM_DEVICE_KT2)
398 {
399 ret = bal_sw_util_esw_flow_remove(iwf_mode, p_flow);
400 }
401 else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
402 {
403 ret = bal_sw_util_dpp_flow_remove(iwf_mode, p_flow);
404 }
405 else
406 {
407 BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on flow remove: 0x%x\n", dev_type );
408 ret = BCM_ERR_INTERNAL;
409 }
410
411 BCM_LOG(INFO, log_id_sw_util, " Return flow remove request with %d on device 0x%x\n", ret, dev_type );
412
413 return ret;
414}
415
416/**
417 * @brief The flow list init function prepare a link list to keep track of flows in the switch util
418 *
419 * @return error code
420 */
421static bcmos_errno bal_sw_util_flow_list_init(void)
422{
423 TAILQ_INIT(&g_swutil_flow_list);
424 return BCM_ERR_OK;
425}
426
427/**
428 * @brief The flow list finish function release all resources allocated in the flow list
429 *
430 * @return error code
431 */
432static bcmos_errno bal_sw_util_flow_list_finish(void)
433{
434 bal_sw_flow *current_entry, *p_temp_entry;
435
436 /* Free all the entries in the list */
437 TAILQ_FOREACH_SAFE(current_entry,
438 &g_swutil_flow_list,
439 flow_next,
440 p_temp_entry)
441 {
442 /* Remove it from the list */
443 TAILQ_REMOVE(&g_swutil_flow_list, current_entry, flow_next);
444
445 bcmos_free(current_entry);
446 }
447 return BCM_ERR_OK;
448}
449
450/**
451 * @brief The flow list search function by flow id
452 *
453 * @param id Flow id that need to match the entry in the list
454 * @return pointer to an element in the list
455 */
456bal_sw_flow *bal_sw_util_flow_list_get_by_id(uint32_t id)
457{
458 bal_sw_flow *p_entry, *p_temp;
459 TAILQ_FOREACH_SAFE(p_entry, &g_swutil_flow_list, flow_next, p_temp)
460 {
461 if( p_entry->id == id)
462 {
463 break;
464 }
465 }
466 /* if reach the end of the list, TAILQ_FOREACH_SAFE set the p_entry to NULL */
467 return p_entry;
468}
469
470/**
471 * @brief The flow list search function by flow id
472 *
473 * @param trap_code Trap id that need to match the entry in the list
474 * @return pointer to an element in the list
475 */
476bal_sw_flow *bal_sw_util_flow_list_get_by_trap_code(uint32_t trap_code)
477{
478 bal_sw_flow *p_entry, *p_temp;
479
480 if (trap_code == 0)
481 {
482 BCM_LOG(WARNING, log_id_sw_util, "Invalid trap code %d in Flow list search by trap code\n", trap_code);
483 return NULL;
484 }
485 TAILQ_FOREACH_SAFE(p_entry, &g_swutil_flow_list, flow_next, p_temp)
486 {
487 if( p_entry->trap_code == trap_code)
488 {
489 break;
490 }
491 }
492 /* if reach the end of the list, TAILQ_FOREACH_SAFE set the p_entry to NULL */
493 return p_entry;
494}
495
496/*
497 * @brief The flow list insert function
498 *
499 * @param entry the element to be added in the link list
500 * @return error code
501*/
502bcmos_errno bal_sw_util_flow_list_insert(bal_sw_flow entry)
503{
504 bal_sw_flow *p_new_entry;
505
506 p_new_entry = bcmos_calloc(sizeof(bal_sw_flow));
507 if(NULL == p_new_entry)
508 {
509 BCM_LOG(ERROR, log_id_sw_util, "Flow list insert out of memory\n");
510 return BCM_ERR_NOMEM;
511 }
512 *p_new_entry = entry;
513 TAILQ_INSERT_TAIL(&g_swutil_flow_list, p_new_entry, flow_next);
514 return BCM_ERR_OK;
515}
516
517/*
518 * @brief The flow list remove function
519 *
520 * @param p_entry Pointer to the element in the link list result from one of the search functions
521 * @return error code
522*/
523bcmos_errno bal_sw_util_flow_list_remove(bal_sw_flow *p_entry)
524{
525 TAILQ_REMOVE(&g_swutil_flow_list, p_entry, flow_next);
526 bcmos_free(p_entry);
527 return BCM_ERR_OK;
528}
529
530
531/*
532 * @brief down Stream Flow classifier check to see if an ACL rule is needed for classification
533 *
534 * In ING SDK, vswitch LIF is mostly used to classify VLAN and ingress port only.
535 * Any packet classification more than that requires an ACL rule to filter the
536 * traffics. This routine check if an ACL is needed.
537 * If only VLAN ids are classify, return FALSE, otherwise return TRUE
538 *
539 * @param p_flow Pointer to the flow object that contains the classifier
540 * @return TRUE or FALSE
541*/
542bcmos_bool bal_sw_util_flow_ds_acl_cls_chk(bcmbal_flow_cfg *p_flow)
543{
544 if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ether_type) ||
545 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ip_proto) ||
546 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_port) ||
547 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_port) ||
548 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_pbits) ||
549 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_pbits) ||
550 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_mac) ||
551 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_mac) ||
552 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_ip) ||
553 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_ip)
554 )
555 return BCMOS_TRUE;
556 else
557 return BCMOS_FALSE;
558}
559
560/*
561 * @brief Up Stream Flow classifier check to see if an ACL rule is needed for classification
562 *
563 * In ING SDK, vswitch LIF is mostly used to classify VLAN and ingress port only.
564 * Any packet classification more than that requires an ACL rule to filter the
565 * traffics. This routine check if an ACL is needed.
566 * If only VLAN ids are classify, return FALSE, otherwise return TRUE
567 *
568 * @param p_flow Pointer to the flow object that contains the classifier
569 * @return TRUE or FALSE
570*/
571bcmos_bool bal_sw_util_flow_us_acl_cls_chk(bcmbal_flow_cfg *p_flow)
572{
573 /* Up Stream Outer Pbits classification is done using PON LIF, no need to use ACL */
574 if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ether_type) ||
575 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ip_proto) ||
576 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_port) ||
577 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_port) ||
578 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_pbits) ||
579 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_mac) ||
580 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_mac) ||
581 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_ip) ||
582 BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_ip)
583 )
584 return BCMOS_TRUE;
585 else
586 return BCMOS_FALSE;
587}
588
589static uint32_t g_flow_inited = 0;
590
591#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
592/**
593 * @brief SWITCH module: flow SET handler
594 *
595 * This routine is called by flow_fsm in the BAL core upon
596 * SET request for flow object.
597 *
598 * @param p_flow Pointer to flow instance
599 * @param opt_type Operation type on flow instance
600 *
601 * @return bcmos_errno
602 */
603bcmos_errno sw_util_flow_set(flow_inst *p_flow, bal_util_oper_flow opt_type)
604{
605 bcmos_errno ret = BCM_ERR_OK;
606
607#ifndef TEST_SW_UTIL_LOOPBACK
608 bal_sw_util_vsi_list_init();
609 if (opt_type == BAL_UTIL_OPER_FLOW_ADD)
610 {
611 if (g_flow_inited == 0)
612 {
613 /* initialized the internal flow link list */
614 bal_sw_util_flow_list_init();
615 /* call flow_init in switch device */
616 bal_sw_util_dpp_flow_init();
617 g_flow_inited = 1;
618 }
619 ret = bal_sw_util_flow_add(p_flow);
620 }
621 else if( BAL_UTIL_OPER_FLOW_REMOVE == opt_type )
622 {
623 ret = bal_sw_util_flow_remove(p_flow);
624 }
625 else if( BAL_UTIL_OPER_FLOW_CLEAR == opt_type )
626 {
627 ret = bal_sw_util_flow_remove(p_flow);
628 }
629 else
630 {
631 BCM_LOG(ERROR, log_id_sw_util, "Only ADD/REMOVE/CLEAR request is supported for FLOW object\n");
632 return BCM_ERR_NOT_SUPPORTED;
633 }
634#else
635 BCM_LOG(INFO, log_id_sw_util, "dummy flow %s SUCCESS\n",
636 ( BAL_UTIL_OPER_FLOW_ADD == opt_type ) ? "flow add" : "flow remove");
637#endif
638
639 return ret;
640}
641
642/**
643 * @brief SWITCH module: flow clean up function
644 *
645 * This routine is called by bal_switch_util() when the BAL core issue finish request
646 *
647 * @return bcmos_errno
648 */
649bcmos_errno sw_util_flow_finish()
650{
651 bcmos_errno ret = BCM_ERR_OK;
652
653#ifndef TEST_SW_UTIL_LOOPBACK
654 if (g_flow_inited )
655 {
656 /* release the internal flow link list */
657 bal_sw_util_flow_list_finish();
658
659 g_flow_inited = 0;
660 }
661#endif
662 return ret;
663}
664/*@}*/