blob: fb1be7bd3915d489d3a11ceba9e8dba8518fc59c [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#include <bal_common.h>
33#include <bcm_dev_log.h>
34#include <bal_msg.h>
35#include "bal_switch_util.h"
36#include "bal_switch_acc_term.h"
37#include "bal_switch_flow.h"
38#include <bal_worker.h>
39/* declare ENV so that the bcm/rx.h in the bal_dpp_acc_term.h can create the correct bcm_pkt_t structure */
40#ifdef ESW_SWITCH
41#define BCM_ESW_SUPPORT 1
42#else
43#define BCM_DNX_SUPPORT 1
44#endif
45#include "esw/bal_esw_acc_term.h"
46#include "dpp/bal_dpp_acc_term.h"
47/* Below local functions are used for real logic only */
48#ifndef TEST_SW_UTIL_LOOPBACK
49#include <arpa/inet.h>
50#include <bcm/init.h>
51#include <bcm/types.h>
52#include <bcm/port.h>
53#include <appl/diag/shell.h> /* for .soc loading */
54
55extern int socdiag_main(int argc, char *argv[]);
56
57/**
58 * @file bal_switch_acc_term.c
59 * @brief BAL Switch util functions that handle access terminal requests
60 * @addtogroup sw_util
61 *
62 */
63
64/*@{*/
65/* forward declaration */
66static void sw_util_bcm_rx_cb (int unit, int port, int reason, unsigned char *p_payload, int payload_len);
67
68/* define a customized dpp packetIn receive registration function.
69 * This function will be called when the HW trap a CPU bound packet
70 */
71static bcm_rx_t dpp_rx_cb_register(int unit, bcm_pkt_t *pkt, void *cookie)
72{
73 int src_port, reason_code, payload_len;
74 unsigned char *p_payload;
75
76 /* extract trap code, ingress port and payload info */
77 src_port = pkt->src_port & 0xff;
78 reason_code = pkt->rx_trap_data;
79 p_payload = pkt->_pkt_data.data + (pkt->tot_len - pkt->pkt_len);
80 payload_len = pkt->pkt_len;
81
82 /* call sw_util_bcm_rx_cb to send packet to the BAL client */
83 sw_util_bcm_rx_cb(unit, src_port, reason_code, p_payload, payload_len);
84 return BCM_RX_HANDLED;
85}
86
87/* The default switch device the switch app is managed */
88#ifdef CONFIG_SWITCH_RPC
89static uint32_t g_dft_dev_id = 2;
90#else
91static uint32_t g_dft_dev_id = 0;
92#endif
93static uint32_t g_iwf_mode = 0;
94static uint32_t g_l2_age_time = 300;
95
96/* flag to determine if we need RPC for switch communication */
97#ifdef CONFIG_SWITCH_RPC
98static uint32_t g_use_rpc = 1;
99#else
100static uint32_t g_use_rpc = 0;
101#endif
102
103/* Socket to be connected to the switch driver msg receiving UDP port */
104bcmos_bool g_pkt_send_is_initialized = BCMOS_FALSE;
105
106static trap_target s_target_device;
107
108/* Index to determine which interface mapping table should be used.
109 * The mapping table is HW specific and depend on how physical wires are lay out
110 * Any customized board may need a different table entry to reflect the connections
111 */
112static bal_swapp_port_map_indx g_intf_maptable = BAL_SWAPP_PORT_MAP_GPON;
113
114 /* the logical interface to KT2 port mapping table
115 the tables is index by technology then logical interface number that used in the BAL CLI
116 the data is the switch port-bit-map number and device number
117*/
118
119/* table with gpon technology
120 based on KT2 port config option 4 - see page 22 on KT2 data sheet */
121/* gpon network interface mapping -
122 * KT2 is for Broadcom experiment purpose - not all function will work */
123bal_swapp_port net_inf_map_gpon[] = {
124 { 27, /* xe0 */ 0},
125 { 28, /* xe1 */ 0},
126 { 30, /* xe2 */ 0},
127 { 33, /* xe3 */ 0},
128 { 40, /* ge24 */ 0},
129 { -1, /* end */ 0}
130 };
131/* ARAD temp mapping xe128 - xe131 as nni ports */
132/* ARAD is for Broadcom experiment purpose - not all function will work */
133bal_swapp_port net_inf_map_exp[] = {
134 { 128, /* xe128 */ 0},
135 { 129, /* xe129 */ 0},
136 { 130, /* xe130 */ 0},
137 { 131, /* xe131 */ 0},
138 { -1, /* end */ 0}
139 };
140/* QAX temp mapping xe128-132 as nni ports 0-4 */
141bal_swapp_port net_inf_map_exp2[] = {
142 { 128, /* xe128 */ 0},
143 { 129, /* xe129 */ 0},
144 { 130, /* xe130 */ 0},
145 { 131, /* xe131 */ 0},
146 { 132, /* xe132 */ 0},
147 { -1, /* end */ 0}
148 };
149
150/* svk4 mapping xe128-133 as nni ports 0-5 */
151bal_swapp_port net_inf_map_svk4[] = {
152 { 128, /* xe128 */ 0},
153 { 129, /* xe129 */ 0},
154 { 130, /* xe130 */ 0},
155 { 131, /* xe131 */ 0},
156 { 132, /* xe132 */ 0},
157 { 133, /* xe133 */ 0},
158 { -1, /* end */ 0}
159 };
160
161/* epon 10g-capable mapping xe128-135 as nni ports 0-7 (best guess - needs to be tested) */
162bal_swapp_port net_inf_map_epon_tdma_10g[] = {
163 { 128, /* xe128 */ 0},
164 { 129, /* xe129 */ 0},
165 { 130, /* xe130 */ 0},
166 { 131, /* xe131 */ 0},
167 { 132, /* xe132 */ 0},
168 { 133, /* xe133 */ 0},
169 { 134, /* xe134 */ 0},
170 { 135, /* xe135 */ 0},
171 { -1, /* end */ 0}
172};
173
174/* epon 1g only mapping - copied from gpon KT2 example above (best guess - needs to be tested) */
175bal_swapp_port net_inf_map_epon_1g[] = {
176 { 27, /* xe0 */ 0},
177 { 28, /* xe1 */ 0},
178 { 30, /* xe2 */ 0},
179 { 33, /* xe3 */ 0},
180 { 40, /* ge24 */ 0},
181 { -1, /* end */ 0}
182};
183
184/* gpon pon interface mapping */
185bal_swapp_port pon_inf_map_gpon[] = {
186 { 5, /* ge4 */ 0},
187 { 6, /* ge5 */ 0},
188 { 2, /* ge1 */ 0},
189 { 1, /* ge0 */ 0},
190 { 8, /* ge7 */ 0},
191 { 7, /* ge6 */ 0},
192 { 4, /* ge3 */ 0},
193 { 3, /* ge2 */ 0},
194 { 12, /* ge11 */ 0},
195 { 19, /* ge18 */ 0},
196 { 10, /* ge9 */ 0},
197 { 15, /* ge14 */ 0},
198 { 11, /* ge10 */ 0},
199 { 17, /* ge16 */ 0},
200 { 9, /* ge8 */ 0},
201 { 13, /* ge12 */ 0},
202 { -1, /* end */ 0}
203 };
204bal_swapp_port pon_inf_map_gpon_v3[] = {
205 { 8, /* ge7 */ 0},
206 { 7, /* ge6 */ 0},
207 { 4, /* ge3 */ 0},
208 { 3, /* ge2 */ 0},
209 { 6, /* ge5 */ 0},
210 { 5, /* ge4 */ 0},
211 { 2, /* ge1 */ 0},
212 { 1, /* ge0 */ 0},
213 { 15, /* ge14 */ 0},
214 { 16, /* ge15 */ 0},
215 { 11, /* ge10 */ 0},
216 { 12, /* ge11 */ 0},
217 { 13, /* ge12 */ 0},
218 { 14, /* ge13 */ 0},
219 { 9, /* ge8 */ 0},
220 { 10, /* ge9 */ 0},
221 { -1, /* end */ 0}
222 };
223/* ARAD temp mapping xe0 - xe3 as PON ports */
224bal_swapp_port pon_inf_map_exp[] = {
225 { 0, /* xe0 */ 0},
226 { 1, /* xe1 */ 0},
227 { 2, /* xe2 */ 0},
228 { 3, /* xe3 */ 0},
229 { -1, /* end */ 0}
230 };
231/* QAX temp mapping xe1-6, as PON ports 0-5 */
232bal_swapp_port pon_inf_map_exp2[] = {
233 { 1, /* xe1 */ 0},
234 { 2, /* xe2 */ 0},
235 { 3, /* xe3 */ 0},
236 { 4, /* xe4 */ 0},
237 { 5, /* xe5 */ 0},
238 { 6, /* xe6 */ 0},
239 { -1, /* end */ 0}
240 };
241
242/* svk4 mapping xe1-4, as PON ports 0-3 */
243bal_swapp_port pon_inf_map_svk4[] = {
244 { 1, /* xe1 */ 0},
245 { 2, /* xe2 */ 0},
246 { 3, /* xe3 */ 0},
247 { 4, /* xe4 */ 0},
248 { -1, /* end */ 0}
249 };
250
251/* epon 10g-capable mapping xe1-8, as PON ports 0-7 (best guess - untested) */
252bal_swapp_port pon_inf_map_epon_tdma_10g[] = {
253 { 1, /* xe1 */ 0},
254 { 2, /* xe2 */ 0},
255 { 3, /* xe3 */ 0},
256 { 4, /* xe4 */ 0},
257 { 5, /* xe5 */ 0},
258 { 6, /* xe6 */ 0},
259 { 7, /* xe7 */ 0},
260 { 8, /* xe8 */ 0},
261 { -1, /* end */ 0}
262};
263
264/* epon 1g mapping xe1-16, as PON ports 0-15 (best guess - untested) */
265bal_swapp_port pon_inf_map_epon_1g[] = {
266 { 1, /* xe1 */ 0},
267 { 2, /* xe2 */ 0},
268 { 3, /* xe3 */ 0},
269 { 4, /* xe4 */ 0},
270 { 5, /* xe5 */ 0},
271 { 6, /* xe6 */ 0},
272 { 7, /* xe7 */ 0},
273 { 8, /* xe8 */ 0},
274 { 9, /* xe9 */ 0},
275 { 10, /* xe10 */ 0},
276 { 11, /* xe11 */ 0},
277 { 12, /* xe12 */ 0},
278 { 13, /* xe13 */ 0},
279 { 14, /* xe14 */ 0},
280 { 15, /* xe15 */ 0},
281 { 16, /* xe16 */ 0},
282 { -1, /* end */ 0}
283};
284
285/* network interface mapping table */
286bal_swapp_port *g_net_inf_map_table[BAL_SWAPP_PORT_MAP__NUM_OF] = {
287 net_inf_map_gpon, /* BAL_SWAPP_PORT_MAP_GPON */
288 net_inf_map_gpon, /* BAL_SWAPP_PORT_MAP_GPON_V3 */
289 net_inf_map_exp, /* BAL_SWAPP_PORT_MAP_EXP */
290 net_inf_map_exp2, /* BAL_SWAPP_PORT_MAP_EXP2 */
291 net_inf_map_svk4, /* BAL_SWAPP_PORT_MAP_SVK4 */
292 net_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
293 net_inf_map_epon_1g, /* BAL_SWAPP_PORT_MAP_EPON_1G */
294 net_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_10G */
295};
296/* pon interface mapping table */
297bal_swapp_port *g_pon_inf_map_table[BAL_SWAPP_PORT_MAP__NUM_OF] = {
298 pon_inf_map_gpon, /* BAL_SWAPP_PORT_MAP_GPON */
299 pon_inf_map_gpon_v3, /* BAL_SWAPP_PORT_MAP_GPON_V3 */
300 pon_inf_map_exp, /* BAL_SWAPP_PORT_MAP_EXP */
301 pon_inf_map_exp2, /* BAL_SWAPP_PORT_MAP_EXP2 */
302 pon_inf_map_svk4, /* BAL_SWAPP_PORT_MAP_SVK4 */
303 pon_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
304 pon_inf_map_epon_1g, /* BAL_SWAPP_PORT_MAP_EPON_1G */
305 pon_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_10G */
306};
307
308/* network interface mapping table size */
309int g_net_inf_map_table_size[BAL_SWAPP_PORT_MAP__NUM_OF] = {
310 sizeof(net_inf_map_gpon)/sizeof(net_inf_map_gpon[0]), /* BAL_SWAPP_PORT_MAP_GPON */
311 sizeof(net_inf_map_gpon)/sizeof(net_inf_map_gpon[0]), /* BAL_SWAPP_PORT_MAP_GPON_V3 */
312 sizeof(net_inf_map_exp)/sizeof(net_inf_map_exp[0]), /* BAL_SWAPP_PORT_MAP_EXP */
313 sizeof(net_inf_map_exp2)/sizeof(net_inf_map_exp2[0]), /* BAL_SWAPP_PORT_MAP_EXP2 */
314 sizeof(net_inf_map_svk4)/sizeof(net_inf_map_svk4[0]), /* BAL_SWAPP_PORT_MAP_SVK4 */
315 sizeof(net_inf_map_epon_tdma_10g)/sizeof(net_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
316 sizeof(net_inf_map_epon_1g)/sizeof(net_inf_map_epon_1g[0]), /* BAL_SWAPP_PORT_MAP_EPON_1G */
317 sizeof(net_inf_map_epon_tdma_10g)/sizeof(net_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_10G */
318};
319/* pon interface mapping table size */
320int g_pon_inf_map_table_size[BAL_SWAPP_PORT_MAP__NUM_OF] = {
321 sizeof(pon_inf_map_gpon)/sizeof(pon_inf_map_gpon[0]), /* BAL_SWAPP_PORT_MAP_GPON */
322 sizeof(pon_inf_map_gpon_v3)/sizeof(pon_inf_map_gpon_v3[0]), /* BAL_SWAPP_PORT_MAP_GPON_V3 */
323 sizeof(pon_inf_map_exp)/sizeof(pon_inf_map_exp[0]), /* BAL_SWAPP_PORT_MAP_EXP */
324 sizeof(pon_inf_map_exp2)/sizeof(pon_inf_map_exp2[0]), /* BAL_SWAPP_PORT_MAP_EXP2 */
325 sizeof(pon_inf_map_svk4)/sizeof(pon_inf_map_svk4[0]), /* BAL_SWAPP_PORT_MAP_SVK4 */
326 sizeof(pon_inf_map_epon_tdma_10g)/sizeof(pon_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
327 sizeof(pon_inf_map_epon_1g)/sizeof(pon_inf_map_epon_1g[0]), /* BAL_SWAPP_PORT_MAP_EPON_1G */
328 sizeof(pon_inf_map_epon_tdma_10g)/sizeof(pon_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_10G */
329};
330
331/**
332 * @brief get the number of valid network interface
333 * @return num_nni number of nni interfaces
334 */
335int bal_bcm_net_inf_map_size_get()
336{
337 return g_net_inf_map_table_size[g_intf_maptable];
338};
339
340 /**
341 * @brief get the number of valid pon interface
342 * @return num_nni number of pon interfaces
343 */
344int bal_bcm_pon_inf_map_size_get()
345{
346 return g_pon_inf_map_table_size[g_intf_maptable];
347};
348
349/**
350 * @brief get KT2 PBM of a network interface from current mapping table
351 *
352 * @param net_inf_id logical nni interface number from CLI
353 *
354 * @return pbm PortBitMap that will be used in bcm api calls
355 */
356uint32_t bal_bcm_net_inf_pbm_get(uint32_t net_inf_id)
357{
358 bal_swapp_port *port = (g_net_inf_map_table[g_intf_maptable] + net_inf_id);
359 return port->pbm_id;
360};
361
362/**
363 * @brief get bal nni port number (index of the mapping table) of a physical nni interface
364 *
365 * @param nni_id physical nni interface in the switch
366 *
367 * @return index index to PortBitMap that contains the physical interface number
368 */
369int bal_bcm_net_inf_idx_get(uint32_t nni_id)
370{
371 int indx;
372 bal_swapp_port *port = g_net_inf_map_table[g_intf_maptable];
373 for( indx = 0; port->pbm_id != -1; indx++)
374 {
375 if (port->pbm_id == nni_id)
376 {
377 break;
378 }
379 port++;
380 }
381 if (port->pbm_id == -1)
382 {
383 return -1;
384 }
385 else
386 {
387 return indx;
388 }
389}
390
391/**
392 * @brief get KT2 device id of a network interface from current mapping table
393 *
394 * @param net_inf_id logical nni interface number from CLI
395 *
396 * @return pbm device number that will be used in bcm api calls
397 */
398int bal_bcm_net_inf_dev_get(uint32_t net_inf_id)
399{
400 if(net_inf_id > sizeof(g_net_inf_map_table))
401 {
402 return bal_bcm_dft_dev_get();
403 }
404 else
405 {
406 bal_swapp_port *port = (g_net_inf_map_table[g_intf_maptable] + net_inf_id);
407 return port->device_id;
408 }
409};
410
411/**
412 * @brief get KT2 PBM of a pon interface from current mapping table
413 *
414 * @param pon_inf_id logical pon interface number from CLI
415 *
416 * @return pbm PortBitMap that will be used in bcm api calls
417 */
418uint32_t bal_bcm_pon_inf_pbm_get(uint32_t pon_inf_id)
419{
420 bal_swapp_port *port = (g_pon_inf_map_table[g_intf_maptable] + pon_inf_id);
421 return port->pbm_id;
422};
423
424/**
425 * @brief get bal pon port number (index of the mapping table) of a physical pon interface
426 *
427 * @param pon_id physical pon interface in the switch
428 *
429 * @return index index to PortBitMap that contains the physical interface number
430 */
431int bal_bcm_pon_inf_idx_get(uint32_t pon_id)
432{
433 int indx;
434 bal_swapp_port *port = g_pon_inf_map_table[g_intf_maptable];
435 for( indx = 0; port->pbm_id != -1; indx++)
436 {
437 if (port->pbm_id == pon_id)
438 {
439 break;
440 }
441 port++;
442 }
443 if (port->pbm_id == -1)
444 {
445 return -1;
446 }
447 else
448 {
449 return indx;
450 }
451}
452
453/**
454 * @brief get KT2 device number of a pon interface from current mapping table
455 *
456 * @param pon_inf_id logical pon interface number from CLI
457 *
458 * @return pbm device number that will be used in bcm api calls
459 */
460int bal_bcm_pon_inf_dev_get(uint32_t pon_inf_id)
461{
462 if(pon_inf_id > sizeof(g_pon_inf_map_table))
463 {
464 return bal_bcm_dft_dev_get();
465 }
466 else
467 {
468 bal_swapp_port *port = (g_pon_inf_map_table[g_intf_maptable] + pon_inf_id);
469 return port->device_id;
470 }
471};
472
473/**
474 * @brief setting the local default device id
475 */
476void bal_bcm_dft_dev_set(uint32_t id)
477{
478 g_dft_dev_id = (int)id;
479}
480
481/**
482 * @brief getting the local default device id
483 */
484uint32_t bal_bcm_dft_dev_get()
485{
486 return g_dft_dev_id;
487}
488
489/**
490 * @brief setting the L2 table aging time (seconds)
491 */
492void bal_bcm_l2_age_time_set(uint32_t age_time)
493{
494 g_l2_age_time = age_time;
495}
496
497/**
498 * @brief getting current L2 table aging time value
499 */
500uint32_t bal_bcm_l2_age_time_get()
501{
502 return g_l2_age_time;
503}
504
505/**
506 * @brief getting the device type
507 */
508uint32_t bal_bcm_dev_type_get(uint32_t id)
509{
510 int rc;
511 bcm_info_t dev_info;
512
513 rc = bcm_info_get(id, &dev_info);
514 if (rc)
515 {
516 return 0;
517 }
518
519 return dev_info.device;
520}
521
522/**
523 * @brief getting the iwf mode of an access terminal
524 */
525uint32_t bal_bcm_iwf_mode_get()
526{
527 /* currently only support one access terminal */
528 BCM_LOG(DEBUG, log_id_sw_util, " Get iwf mode for acc_term\n");
529 return g_iwf_mode;
530}
531
532/**
533 * @brief setting the use of RPC (remote) or not (local)
534 */
535void bal_bcm_use_rpc_set(uint32_t use_rpc)
536{
537 g_use_rpc = (int)use_rpc;
538}
539
540/**
541 * @brief getting the use of RPC (remote) or not (local)
542 */
543bcmos_bool bal_bcm_use_rpc_get(void)
544{
545 if (g_use_rpc)
546 {
547 return BCMOS_TRUE;
548 }
549 else
550 {
551 return BCMOS_FALSE;
552 }
553}
554
555static void sw_util_bcm_rx_cb (int unit, int port, int reason, unsigned char *p_payload, int payload_len)
556{
557 int i, len, obj_len;
558 unsigned char *payload;
559 char bytestr[32];
560 char *p_bytestr = bytestr;
561
562 BCM_LOG(INFO, log_id_sw_util, "BAL: Captured packet from datapath (len: %d bytes)\n", payload_len);
563
564 BCM_LOG(DEBUG, log_id_sw_util, " ingress port %d\n", port);
565 BCM_LOG(DEBUG, log_id_sw_util, " rcv reason 0x%x\n", reason);
566
567 len = (payload_len > 64)? 64 : payload_len;
568
569 /* dump out the captured packet */
570 payload = p_payload;
571 BCM_LOG(DEBUG, log_id_sw_util, " payload: (first %d bytes shown)", len);
572 for(i=0; i<len; i++)
573 {
574 if ( i%8 == 0)
575 {
576 sprintf(p_bytestr, "\n");
577 BCM_LOG(DEBUG, log_id_sw_util, "%s", bytestr);
578 p_bytestr = bytestr;
579
580 }
581 sprintf(p_bytestr, " %02x", *payload++);
582 p_bytestr += 3;
583 }
584
585 /* Log the string being crafted when the loop terminated */
586 sprintf(p_bytestr, "\n");
587 BCM_LOG(DEBUG, log_id_sw_util, "%s", bytestr);
588
589 /* Send Auto Indication */
590 if ( p_bal_core_to_api_ind_queue )
591 {
592 bcmbal_packet_cfg *p_ind_msg = NULL;
593 bcmbal_packet_key key;
594 bal_sw_flow *p_flow_elm;
595 int tmp_port;
596
597 /* find the flow info corresponding to this trap REASON */
598 p_flow_elm = bal_sw_util_flow_list_get_by_trap_code(reason);
599 if(p_flow_elm == NULL)
600 {
601 BCM_LOG(WARNING, log_id_sw_util, " TrapCallBack: Can't match trap code 0x%x to element in flow list\n", reason);
602 return;
603 }
604
605 /* The packet indication object contains the bcmbal_packet_cfg structure plus the captured packet
606 * content
607 */
608 obj_len = payload_len + sizeof(bcmbal_packet_cfg);
609
610 p_ind_msg = bcmbal_msg_calloc(obj_len);
611
612 if(p_ind_msg == NULL)
613 {
614 BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: No memory to send indication\n");
615 return;
616 }
617
618 key.packet_send_dest.type = BCMBAL_DEST_TYPE_HOST;
619
620 BCMBAL_CFG_INIT(p_ind_msg, packet, key);
621
622 BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_id, p_flow_elm->id);
623 BCMBAL_CFG_PROP_SET(p_ind_msg, packet, svc_port, p_flow_elm->svc_port);
624 BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_cookie, p_flow_elm->flow_cookie);
625
626 /* first search the PON table */
627 tmp_port = bal_bcm_pon_inf_idx_get(port);
628 if( tmp_port != -1)
629 {
630 BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_type, BCMBAL_FLOW_TYPE_UPSTREAM);
631 BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_id, tmp_port);
632 BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_type, BCMBAL_INTF_TYPE_PON);
633 }
634 else /* if failed, search for NNI table */
635 {
636 tmp_port = bal_bcm_net_inf_idx_get(port);
637 if( tmp_port != -1)
638 {
639 BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_type, BCMBAL_FLOW_TYPE_DOWNSTREAM);
640 BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_id, tmp_port);
641 BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_type, BCMBAL_INTF_TYPE_NNI);
642 }
643 }
644 /* if both failed, return */
645 if(tmp_port == -1)
646 {
647 /* something went wrong, free up the message */
648 bcmbal_msg_free(p_ind_msg);
649 BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: can't match ingress port to bal port tables\n");
650 return;
651 }
652
653 ((bcmbal_obj *)p_ind_msg)->status = BCM_ERR_OK;
654 ((bcmbal_obj *)p_ind_msg)->obj_type = BCMBAL_OBJ_ID_PACKET;
655 ((bcmbal_obj *)p_ind_msg)->group = BCMBAL_MGT_GROUP_AUTO;
656
657 /* now copy the contents of the packet */
658 p_ind_msg->data.pkt.val = (uint8_t *)(p_ind_msg + 1);
659 memcpy(p_ind_msg->data.pkt.val, p_payload, payload_len);
660
661 /* and record the length of the captured packet */
662 p_ind_msg->data.pkt.len = payload_len;
663
664 BCMBAL_PROP_SET_PRESENT(p_ind_msg, packet, _cfg, pkt);
665
666 BCM_LOG(INFO, log_id_sw_util, " TrapCallBack: Flow id = %d, type=%d, Interface id = %d, type=%d, svc_port=%d\n",
667 p_ind_msg->data.flow_id, p_ind_msg->data.flow_type,
668 p_ind_msg->data.intf_id, p_ind_msg->data.intf_type,
669 p_ind_msg->data.svc_port);
670
671 /* Send this indication straight to the API client
672 */
673 bcmbal_msg_hdr_set(p_ind_msg,
674 BCMBAL_MGMT_API_IND_MSG,
675 BAL_MSG_TYPE_AUTO_IND,
676 BAL_SUBSYSTEM_CORE,
677 BCMBAL_OBJ_ID_PACKET,
678 0, /* operation code */
679 0); /* exchange id */
680
681 if(BCM_ERR_OK != bcmbal_msg_send(p_bal_core_to_api_ind_queue,
682 p_ind_msg,
683 BCMOS_MSG_SEND_AUTO_FREE))
684 {
685 BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: send auto indication failed\n");
686 }
687 else
688 {
689 BCM_LOG(DEBUG, log_id_sw_util, " TrapCallBack: auto indication sent\n");
690 }
691 }
692 else
693 {
694 BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: no auto indication queue\n");
695 }
696 return;
697}
698
699/**
700 * @brief Connect access terminal
701 *
702 * This routine is called by acc_term_fsm in the BAL core
703 * Upon receiving the request from the core, this function
704 * assign the device number that each logical nni or pon interface belong
705 * and restrict the egress ports of each interface. This mapping is highly
706 * topology dependent and should be customized according to the actual hardware
707 * layout.
708 * @param p_acc_term Pointer to access terminal instance
709 *
710 * @return bcmos_errno
711 */
712static bcmos_errno sw_util_access_terminal_connect(acc_term_inst *p_acc_term)
713{
714 bcmos_errno ret = BCM_ERR_INTERNAL;
715 int rc;
716 bal_swapp_port *port;
717 char *argv[] = { "socdiag", NULL };
718 uint32_t dev_type;
719
720 BCM_LOG(INFO, log_id_sw_util, " Got a access terminal SET\n");
721
722 /* make sure the abstraction layer is initialized - no harm to initialize multiple time */
723 bcmos_init();
724
725 /* Initialize SDK */
726 rc = socdiag_main(1, argv);
727 if (rc)
728 {
729 BCM_LOG(ERROR, log_id_sw_util, " Init BCM SDK failed - %d\n", rc);
730 return BCM_ERR_INTERNAL;
731 }
732
733 BCM_LOG(INFO, log_id_sw_util, " %s RPC\n", (1 == g_use_rpc) ? "Using" : "Not using" );
734
735 /* use a soc script to establish rpc connection if switch is remotely located */
736 if (bal_bcm_use_rpc_get())
737 {
738 sleep(3); /* allow remote device to settle */
739
740 BCM_LOG(INFO, log_id_sw_util, " starting RPC connection\n");
741 rc = sh_rcload_file(-1, NULL, "rpc.soc", 0);
742 if (rc)
743 {
744 BCM_LOG(ERROR, log_id_sw_util, " start RPC connection failed\n");
745 return BCM_ERR_INTERNAL;
746 }
747
748 }
749
750 BCM_LOG(INFO, log_id_sw_util, " Using interface table: %d Device: %d\n", g_intf_maptable, g_dft_dev_id );
751
752 /* setup the device ID - This is very hardware specific */
753 port = g_net_inf_map_table[g_intf_maptable];
754 /* -1 indicate end of table */
755 while(port->pbm_id != -1)
756 {
757 port->device_id = g_dft_dev_id;
758 port++;
759 }
760
761 port = g_pon_inf_map_table[g_intf_maptable];
762 while(port->pbm_id != -1)
763 {
764 port->device_id = g_dft_dev_id;
765 port++;
766 }
767 /* get the switch model from the chip */
768 dev_type = bal_bcm_dev_type_get(g_dft_dev_id);
769 if (dev_type == 0)
770 {
771 BCM_LOG(ERROR, log_id_sw_util, " Error retrieving device type on access-terminal connect: 0x%x\n", dev_type);
772 return BCM_ERR_INTERNAL;
773 }
774
775 /* set up the valid egress ports for net/pon facing ports */
776 if (dev_type == BCM_DEVICE_KT2)
777 {
778 ret = sw_util_esw_acc_term_connect(g_net_inf_map_table[g_intf_maptable], g_pon_inf_map_table[g_intf_maptable]);
779 }
780 else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
781 {
782 /* for rpc case, dpp use a special api to register rx callback.
783 for non-rpc use case, use bcm_rx_register() to register the rx callback
784 */
785 if (bal_bcm_use_rpc_get())
786 {
787 /* if the trap receive udp port in bal_config.ini is not zero, start a receiving thread */
788 if(bal_bcm_trap_rcv_port_get())
789 {
790 sw_util_dpp_rx_cb_register(bal_bcm_dft_dev_get(), sw_util_bcm_rx_cb);
791 }
792 else
793 {
794 BCM_LOG(ERROR, log_id_sw_util, "Missing UDP port number for RPC packet In receiver \n");
795 return BCM_ERR_INTERNAL;
796 }
797 }
798 else
799 {
800 bcm_rx_register(bal_bcm_dft_dev_get(), "Bal Cpu Traps", dpp_rx_cb_register, 50, NULL, BCM_RCO_F_ALL_COS);
801 }
802
803 ret = sw_util_dpp_acc_term_connect(g_net_inf_map_table[g_intf_maptable], g_pon_inf_map_table[g_intf_maptable]);
804 }
805
806 BCM_LOG(INFO, log_id_sw_util, " Return access terminal connect request with %d on device 0x%x\n", ret, dev_type );
807
808 /* for now, only support one iwf */
809 g_iwf_mode = (uint32_t)p_acc_term->api_req_acc_term_obj_info.data.iwf_mode;
810
811 return ret;
812}
813
814/**
815 * @brief getting the interface mapping table that applied to the HW connections
816 */
817bal_swapp_port_map_indx bal_bcm_intf_maptable_get()
818{
819 return g_intf_maptable;
820}
821
822/**
823 * @brief SWITCH module: internal packet_send function
824 *
825 * This routine distribute the SEND function to supported switch family
826 *
827 * @param dst_port_id Switch port id the packet is going to be sent out
828 * @param reason REASON_SEND_TO_NNI or REASON_SEND_TO_PON
829 * @param payload pointer to the data
830 * @param payload_len the length of the data
831 * @param tunnel_id pon port tunnel id if REASON_SEND_TO_PON
832 *
833 * @return bcmos_errno
834 */
835static bcmos_errno sw_util_pkt_send_intl(int dst_port_id,
836 int reason,
837 unsigned char *payload,
838 int payload_len,
839 int tunnel_id)
840{
841 uint32_t dev_type;
842 bcmos_errno ret = BCM_ERR_OK;
843
844 /* get the switch chip type from default device id
845 TBD - in the future, the device id should be obtained from port mapping table */
846 dev_type = bal_bcm_dev_type_get(g_dft_dev_id);
847 if (dev_type == 0)
848 {
849 BCM_LOG(ERROR, log_id_sw_util, " Error retrieving device type on pkt send: 0x%x\n", dev_type);
850 return BCM_ERR_INTERNAL;
851 }
852
853 /* set up the valid egress ports for net/pon facing ports */
854 if (dev_type == BCM_DEVICE_KT2)
855 {
856 return BCM_ERR_NOT_SUPPORTED;
857 }
858 else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
859 {
860 ret = sw_util_dpp_pkt_send(dst_port_id, reason, payload, payload_len, s_target_device, tunnel_id);
861 }
862 else
863 {
864 ret = BCM_ERR_NOT_SUPPORTED;
865 }
866
867 BCM_LOG(INFO, log_id_sw_util, " Return access terminal connect request with %d on device 0x%x\n", ret, dev_type );
868
869 return ret;
870}
871
872#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
873
874/* the listening UDP port that the switch will send the trapped messages */
875static uint32_t g_trap_rcv_port = 0;
876
877/**
878 * @brief set the receiving UDP port for trap packets - from config file
879 */
880uint32_t bal_bcm_trap_rcv_port_set(uint32_t udp_port)
881{
882 g_trap_rcv_port = udp_port;
883 return 0;
884}
885
886/**
887 * @brief getting the receiving UDP port for trap packets
888 */
889uint32_t bal_bcm_trap_rcv_port_get()
890{
891 return g_trap_rcv_port;
892}
893
894
895/* the global portChannel DownStream Max rate scheduling mode */
896static uint32_t g_ds_sched_mode = 0; /* default to strict priority */
897
898/**
899 * @brief set the DS max rate scheduling mode - from config file
900 */
901uint32_t bal_bcm_ds_sched_mode_set(uint32_t sched_mode)
902{
903 g_ds_sched_mode = sched_mode;
904 return 0;
905}
906
907/**
908 * @brief getting the DS max rate scheduling mode
909 */
910uint32_t bal_bcm_ds_sched_mode_get()
911{
912 return g_ds_sched_mode;
913}
914
915/**
916 * @brief SWITCH module: access terminal SET handler
917 *
918 * This routine is called by acc_term_fsm in the BAL core upon
919 * SET request for acc_terminal object.
920 *
921 * @param p_acc_term Pointer to access terminal instance
922 * @param opt_type Operation type on access terminal instance
923 *
924 * @return bcmos_errno
925 */
926bcmos_errno sw_util_access_terminal_set(acc_term_inst *p_acc_term,
927 bal_util_oper_acc_term opt_type)
928{
929 bcmos_errno ret = BCM_ERR_OK;
930
931 if (opt_type != BAL_UTIL_OPER_ACC_TERM_CONNECT)
932 {
933 BCM_LOG(ERROR, log_id_sw_util, " Access terminal currently supports only CONNECT request\n");
934 return BCM_ERR_NOT_SUPPORTED;
935 }
936
937#ifndef TEST_SW_UTIL_LOOPBACK
938 ret = sw_util_access_terminal_connect(p_acc_term);
939#else
940 BCM_LOG(INFO, log_id_sw_util, " dummy SUCCESS\n");
941#endif
942
943 return ret;
944}
945
946/**
947 * @brief setting the interface mapping table that applied to the HW connections
948 */
949int bal_bcm_intf_maptable_set(uint32_t intf_maptable)
950{
951 int ret = 0;
952#ifndef TEST_SW_UTIL_LOOPBACK
953 switch(intf_maptable)
954 {
955 case 0:
956 g_intf_maptable = BAL_SWAPP_PORT_MAP_GPON;
957 break;
958 case 1:
959 g_intf_maptable = BAL_SWAPP_PORT_MAP_GPON_V3;
960 break;
961 case 2:
962 g_intf_maptable = BAL_SWAPP_PORT_MAP_EXP;
963 break;
964 case 3:
965 g_intf_maptable = BAL_SWAPP_PORT_MAP_EXP2;
966 break;
967 case 4:
968 g_intf_maptable = BAL_SWAPP_PORT_MAP_SVK4;
969 break;
970 case 5:
971 g_intf_maptable = BAL_SWAPP_PORT_MAP_EPON_TDMA;
972 break;
973 case 6:
974 g_intf_maptable = BAL_SWAPP_PORT_MAP_EPON_1G;
975 break;
976 case 7:
977 g_intf_maptable = BAL_SWAPP_PORT_MAP_EPON_10G;
978 break;
979 default:
980 BCM_LOG(ERROR, log_id_sw_util, " Mapping Table Id %d is not supported\n", intf_maptable);
981 ret = BCM_ERR_NOT_SUPPORTED;
982 break;
983 }
984#endif
985 return ret;
986}
987
988/**
989 * @brief SWITCH module: packet_send
990 *
991 * This routine is called by work thread in the BAL core upon
992 * user request to send a raw packet out of a switch port.
993 *
994 * @param dst_port_id Switch port id the packet is going to be sent out
995 * @param reason REASON_SEND_TO_NNI or REASON_SEND_TO_PON
996 * @param payload pointer to the data
997 * @param payload_len the length of the data
998 * @param tunnel_id pon tunnel_id
999 *
1000 * @return bcmos_errno
1001 */
1002bcmos_errno sw_util_pkt_send(int dst_port_id,
1003 int reason,
1004 unsigned char *payload,
1005 int payload_len,
1006 int tunnel_id)
1007{
1008 bcmos_errno ret = BCM_ERR_OK;
1009
1010 if ( reason != REASON_SEND_TO_NNI && reason != REASON_SEND_TO_PON)
1011 {
1012 BCM_LOG(ERROR, log_id_sw_util, " pkt_send currently does not support reason %d\n", reason);
1013 return BCM_ERR_NOT_SUPPORTED;
1014 }
1015
1016 if ( reason == REASON_SEND_TO_NNI && BCMOS_FALSE == bcm_topo_nni_is_valid(dst_port_id))
1017 {
1018 BCM_LOG(ERROR, log_id_sw_util, " pkt_send to invalid nni port %d\n", dst_port_id);
1019 return BCM_ERR_PARM;
1020 }
1021
1022#ifndef TEST_SW_UTIL_LOOPBACK
1023 ret = sw_util_pkt_send_intl(dst_port_id, reason, payload, payload_len, tunnel_id);
1024#else
1025 BCM_LOG(INFO, log_id_sw_util, " dummy SUCCESS\n");
1026#endif
1027
1028 return ret;
1029}
1030
1031/*
1032 * Called from bal_core to set up the packet out server IP:port (i.e. the bcm_user process location)
1033 * when Switch is on the same board where the core is run, there is no RPC and this init function should not be called
1034 */
1035bcmos_errno sw_util_pkt_send_init(const char *pkt_send_server_ip, uint16_t pkt_send_server_listen_port)
1036{
1037 bcmos_errno ret = BCM_ERR_OK;
1038
1039#ifndef TEST_SW_UTIL_LOOPBACK
1040
1041 do
1042 {
1043 /* If the packet_out interface has already been initialized, just return OK */
1044 if(g_pkt_send_is_initialized == BCMOS_FALSE)
1045 {
1046#ifdef CONFIG_SWITCH_RPC
1047 /*
1048 * Set up the socket to be used for sending "packet send" messages
1049 * to the bcm.user server
1050 */
1051 if((s_target_device.socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
1052 {
1053 ret = BCM_ERR_NORES;
1054 break;
1055 }
1056
1057 s_target_device.addr.sin_family = AF_INET;
1058 inet_pton(s_target_device.addr.sin_family, pkt_send_server_ip, &s_target_device.addr.sin_addr.s_addr);
1059 s_target_device.addr.sin_port = htons(pkt_send_server_listen_port);
1060#endif /* CONFIG_SWITCH_RPC */
1061 g_pkt_send_is_initialized = BCMOS_TRUE;
1062 }
1063
1064 }
1065 while(0);
1066
1067#endif /*TEST_SW_UTIL_LOOPBACK*/
1068
1069 return ret;
1070}
1071/*@}*/