blob: ad8d4a7a37b061e4228b5e1b20b53ea6c3b8a417 [file] [log] [blame]
/*
<:copyright-BRCM:2016:DUAL/GPL:standard
Broadcom Proprietary and Confidential.(c) 2016 Broadcom
All Rights Reserved
Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:
As a special exception, the copyright holders of this software give
you permission to link this software with independent modules, and
to copy and distribute the resulting executable under terms of your
choice, provided that you also meet, for each linked independent
module, the terms and conditions of the license of that module.
An independent module is a module which is not derived from this
software. The special exception does not apply to any modifications
of the software.
Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.
:>
*/
#include <bcmolt_host_api.h>
#include "bcmolt_user_appl_gpon_utils.h"
#include <bcmolt_dev_selector.h>
static bcmcli_entry *gpon_utils_cli_dir;
static bcmcli_entry *gpon_utils_cli_top_dir;
static bcmos_bool gpon_utils_is_registered;
static bcmos_errno bcmolt_user_appl_gpon_utils_create(bcmcli_entry *top_dir);
#define MAX_GEM_PORTS_FOR_SEND 64
#define MAX_ONUS_FOR_SEND 64
#define MAX_PACKET_SIZE 2048
typedef enum
{
GENERATED_PACKET_PATTERN_BYTE_CYCLE,
GENERATED_PACKET_PATTERN_WORD_CYCLE,
GENERATED_PACKET_PATTERN_CONST
} generated_packet_pattern;
typedef enum
{
PON_MODE_GPON,
PON_MODE_XGPON,
PON_MODE_INVALID
} pon_mode;
static uint8_t saved_packet[MAX_PACKET_SIZE];
static bcmolt_packet_type saved_packet_type;
static bcmos_bool saved_packet_calc_crc;
static uint16_t saved_packet_len = 0;
static void gpon_utils_cli_dir_cli_destroy(void)
{
if (gpon_utils_cli_dir)
{
bcmcli_token_destroy(gpon_utils_cli_dir);
gpon_utils_cli_dir = NULL;
}
}
/* Current device change indication */
static void bcmolt_user_appl_gpon_utils_device_change_ind(bcmcli_session *session, bcmolt_devid dev)
{
bcmolt_system_mode system_mode;
bcmos_errno err = bcmolt_system_mode_get(dev, &system_mode);
if (err != BCM_ERR_OK)
{
bcmcli_session_print(session, "Error device Id\n");
return;
}
if (system_mode == BCMOLT_SYSTEM_MODE_GPON__16_X ||
system_mode == BCMOLT_SYSTEM_MODE_GPON__8_X ||
system_mode == BCMOLT_SYSTEM_MODE_GPON__4_X ||
system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__8_X ||
system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__4_X ||
system_mode == BCMOLT_SYSTEM_MODE_XGS__2_X_10_G ||
system_mode == BCMOLT_SYSTEM_MODE_NGPON2__2_X_10_G)
{
bcmcli_session_print(session, "Building gpon_utils CLI for device %d\n", dev);
err = bcmolt_user_appl_gpon_utils_create(gpon_utils_cli_top_dir);
if (err)
{
bcmcli_session_print(session, "Error building gpon_utils CLI\n");
}
}
else
{
gpon_utils_cli_dir_cli_destroy();
}
}
static inline pon_mode pon_mode_get(bcmolt_pon_ni pon_id)
{
bcmolt_system_mode system_mode;
bcmos_errno err = bcmolt_system_mode_get(current_device, &system_mode);
if (err != BCM_ERR_OK)
{
return PON_MODE_INVALID;
}
if (system_mode == BCMOLT_SYSTEM_MODE_GPON_8_XGPON_4_X_COEXISTENCE)
{
/* special handling for the 8x GPON / 4x XGPON co-existence mode */
return pon_id < 8 ? PON_MODE_XGPON : PON_MODE_GPON;
}
else if (bcmolt_obj_tag_valid_for_system_mode(system_mode, BCMOLT_OBJ_TAG_GPON))
{
return PON_MODE_GPON;
}
else if (bcmolt_obj_tag_valid_for_system_mode(system_mode, BCMOLT_OBJ_TAG_XGPON))
{
return PON_MODE_XGPON;
}
else
{
return PON_MODE_INVALID;
}
}
static bcmos_errno build_packet(bcmcli_session *session, bcmolt_packet_type type)
{
uint16_t i;
bcmos_bool calc_crc = (bcmos_bool)bcmcli_find_named_parm(session, "calc_crc")->value.unumber;
uint16_t packet_size = (uint16_t)bcmcli_find_named_parm(session, "packet_size")->value.unumber;
generated_packet_pattern pattern =
(generated_packet_pattern)bcmcli_find_named_parm(session, "pattern")->value.unumber;
uint8_t const_value = (uint8_t)bcmcli_find_named_parm(session, "const_value")->value.unumber;
uint16_t data_offset;
/* save packet type / size / CRC flag */
saved_packet_type = type;
saved_packet_len = packet_size;
saved_packet_calc_crc = calc_crc;
if (type == BCMOLT_PACKET_TYPE_CPU)
{
bcmos_mac_address eth_da = bcmcli_find_named_parm(session, "eth_da")->value.mac;
bcmos_mac_address eth_sa = bcmcli_find_named_parm(session, "eth_sa")->value.mac;
/* copy destination MAC */
memcpy(saved_packet, &eth_da, 6);
/* copy source MAC */
memcpy(&saved_packet[6], &eth_sa, 6);
/* write EtherType of 0000 */
memset(&saved_packet[12], 0, 2);
/* data starts after EtherType */
data_offset = 14;
}
else
{
/* fill the entire packet */
data_offset = 0;
}
/* fill the rest of the buffer using the specified data pattern */
switch (pattern)
{
case GENERATED_PACKET_PATTERN_BYTE_CYCLE:
const_value = 0;
for (i = data_offset; i < packet_size; i++)
{
saved_packet[i] = const_value++;
}
break;
case GENERATED_PACKET_PATTERN_WORD_CYCLE:
/* first 4 bytes = 00000000, next 4 = 11111111, next 4 = 22222222, etc */
const_value = 0;
for (i = data_offset; i < packet_size; i += 4)
{
uint16_t j;
for (j = i; j < i + 4 && j < packet_size; j++)
{
saved_packet[j] = const_value;
}
const_value = (const_value == 0xFF) ? 0 : const_value + 0x11;
}
break;
case GENERATED_PACKET_PATTERN_CONST:
for (i = data_offset; i < packet_size; i++)
{
saved_packet[i] = const_value;
}
break;
default:
bcmcli_session_print(session, "[Error] Invalid pattern: %u\n", pattern);
return BCM_ERR_INTERNAL;
}
return BCM_ERR_OK;
}
static bcmos_errno build_cpu_packet_cb(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
{
bcmos_errno err = build_packet(session, BCMOLT_PACKET_TYPE_CPU);
if (err == BCM_ERR_OK)
{
bcmcli_session_print(session, "CPU packet buffer saved successfully\n");
}
else
{
bcmcli_session_print(session, "[Error] saving CPU packet buffer: %s\n", bcmos_strerror(err));
}
return err;
}
static bcmos_errno build_omci_packet_cb(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
{
bcmos_errno err = build_packet(session, BCMOLT_PACKET_TYPE_OMCI);
if (err == BCM_ERR_OK)
{
bcmcli_session_print(session, "OMCI packet buffer saved successfully\n");
}
else
{
bcmcli_session_print(session, "[Error] saving OMCI packet buffer: %s\n", bcmos_strerror(err));
}
return err;
}
static bcmos_errno send_packet_to_gpon_gem_list(bcmcli_session *session, uint16_t gem_count, bcmolt_gpon_gem_id *gems)
{
uint16_t count = 1;
uint16_t i;
uint16_t gem_idx;
bcmos_errno err;
bcmcli_cmd_parm *parm;
bcmolt_devid device = (bcmolt_devid)bcmcli_find_named_parm(session, "device")->value.unumber;
bcmolt_pon_ni pon_ni = (bcmolt_pon_ni)bcmcli_find_named_parm(session, "pon_ni")->value.unumber;
bcmolt_gpon_ni_key pon_ni_key = { .pon_ni = pon_ni };
bcmolt_gpon_gem_id_list_u8_max_16 gem_port_list;
bcmolt_gpon_ni_cpu_packets proxy;
bcmolt_u8_list_u32_max_2048 buffer = { .len = saved_packet_len, .val = saved_packet };
if (saved_packet_len == 0)
{
bcmcli_session_print(session, "[Error] you must build/save a packet before you can send it\n");
return BCM_ERR_PARM;
}
parm = bcmcli_find_named_parm(session, "count");
if (parm != NULL)
{
count = (uint16_t)parm->value.unumber;
}
bcmcli_session_print(
session,
"Sending %u proxy packet%s to %u GEM port%s...\n",
count,
count == 1 ? "" : "s",
gem_count,
gem_count == 1 ? "" : "s");
/* build the proxy API message, except the GEM port list */
BCMOLT_PROXY_INIT(&proxy, gpon_ni, cpu_packets, pon_ni_key);
BCMOLT_PROXY_PROP_SET(&proxy, gpon_ni, cpu_packets, packet_type, saved_packet_type);
BCMOLT_PROXY_PROP_SET(&proxy, gpon_ni, cpu_packets, calc_crc, saved_packet_calc_crc);
BCMOLT_PROXY_PROP_SET(&proxy, gpon_ni, cpu_packets, buffer, buffer);
/* call the proxy API <count> times */
for (i = 0; i < count; i++)
{
/* we may need to split this up into multiple API calls (only 16 GEM ports are allowed per proxy API) */
for (gem_idx = 0; gem_idx < gem_count; gem_idx += 16)
{
gem_port_list.len = MIN(16, gem_count - gem_idx);
gem_port_list.val = &gems[gem_idx];
BCMOLT_PROXY_PROP_SET(&proxy, gpon_ni, cpu_packets, gem_port_list, gem_port_list);
err = bcmolt_proxy_send(device, &proxy.hdr);
if (err != BCM_ERR_OK)
{
bcmcli_session_print(
session,
"[Error] proxy send: packet index %u GEM index %u: %s\n",
i,
gem_idx,
bcmos_strerror(err));
return err;
}
}
}
bcmcli_session_print(session, "%u proxy packet%s sent successfully!\n", count, count == 1 ? "" : "s");
return BCM_ERR_OK;
}
static bcmos_errno send_packet_to_xgpon_gem_list(bcmcli_session *session, uint16_t gem_count, bcmolt_xgpon_gem_id *gems)
{
uint16_t count = 1;
uint16_t i;
uint16_t gem_idx;
bcmos_errno err;
bcmcli_cmd_parm *parm;
bcmolt_devid device = (bcmolt_devid)bcmcli_find_named_parm(session, "device")->value.unumber;
bcmolt_pon_ni pon_ni = (bcmolt_pon_ni)bcmcli_find_named_parm(session, "pon_ni")->value.unumber;
bcmolt_xgpon_ni_key pon_ni_key = { .pon_ni = pon_ni };
bcmolt_xgpon_gem_id_list_u8_max_16 gem_port_list;
bcmolt_xgpon_ni_cpu_packets proxy;
bcmolt_u8_list_u32_max_2048 buffer = { .len = saved_packet_len, .val = saved_packet };
if (saved_packet_len == 0)
{
bcmcli_session_print(session, "[Error] you must build/save a packet before you can send it\n");
return BCM_ERR_PARM;
}
parm = bcmcli_find_named_parm(session, "count");
if (parm != NULL)
{
count = (uint16_t)parm->value.unumber;
}
bcmcli_session_print(
session,
"Sending %u proxy packet%s to %u GEM port%s...\n",
count,
count == 1 ? "" : "s",
gem_count,
gem_count == 1 ? "" : "s");
/* build the proxy API message, except the GEM port list */
BCMOLT_PROXY_INIT(&proxy, xgpon_ni, cpu_packets, pon_ni_key);
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_ni, cpu_packets, packet_type, saved_packet_type);
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_ni, cpu_packets, calc_crc, saved_packet_calc_crc);
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_ni, cpu_packets, buffer, buffer);
/* call the proxy API <count> times */
for (i = 0; i < count; i++)
{
/* we may need to split this up into multiple API calls (only 16 GEM ports are allowed per proxy API) */
for (gem_idx = 0; gem_idx < gem_count; gem_idx += 16)
{
gem_port_list.len = MIN(16, gem_count - gem_idx);
gem_port_list.val = &gems[gem_idx];
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_ni, cpu_packets, gem_port_list, gem_port_list);
err = bcmolt_proxy_send(device, &proxy.hdr);
if (err != BCM_ERR_OK)
{
bcmcli_session_print(
session,
"[Error] proxy send: packet index %u GEM index %u: %s\n",
i,
gem_idx,
bcmos_strerror(err));
return err;
}
}
}
bcmcli_session_print(session, "%u proxy packet%s sent successfully!\n", count, count == 1 ? "" : "s");
return BCM_ERR_OK;
}
static bcmos_errno send_to_gem_cb(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
{
bcmcli_cmd_parm *gem_parm = bcmcli_find_named_parm(session, "gem");
bcmolt_pon_ni pon_id = (bcmolt_pon_ni)bcmcli_find_named_parm(session, "pon_ni")->value.unumber;
uint16_t i;
pon_mode mode = pon_mode_get(pon_id);
if (mode == PON_MODE_GPON)
{
static bcmolt_gpon_gem_id gem_id_buf[MAX_GEM_PORTS_FOR_SEND];
for (i = 0; i < gem_parm->array_size; i++)
{
gem_id_buf[i] = (bcmolt_gpon_gem_id)gem_parm->values[i].unumber;
}
return send_packet_to_gpon_gem_list(session, (uint16_t)gem_parm->array_size, gem_id_buf);
}
else if (mode == PON_MODE_XGPON)
{
static bcmolt_xgpon_gem_id gem_id_buf[MAX_GEM_PORTS_FOR_SEND];
for (i = 0; i < gem_parm->array_size; i++)
{
gem_id_buf[i] = (bcmolt_xgpon_gem_id)gem_parm->values[i].unumber;
}
return send_packet_to_xgpon_gem_list(session, (uint16_t)gem_parm->array_size, gem_id_buf);
}
else
{
bcmcli_session_print(session, "[Error] Invalid system mode\n");
return BCM_ERR_INTERNAL;
}
}
static bcmos_errno send_packet_to_gpon_onu_list(bcmcli_session *session, uint16_t onu_count, bcmolt_gpon_onu_id *onus)
{
uint16_t count = 1;
uint16_t i;
uint16_t onu_idx;
bcmos_errno err;
bcmcli_cmd_parm *parm;
bcmolt_devid device = (bcmolt_devid)bcmcli_find_named_parm(session, "device")->value.unumber;
bcmolt_pon_ni pon_ni = (bcmolt_pon_ni)bcmcli_find_named_parm(session, "pon_ni")->value.unumber;
if (saved_packet_len == 0)
{
bcmcli_session_print(session, "[Error] you must build/save a packet before you can send it\n");
return BCM_ERR_PARM;
}
parm = bcmcli_find_named_parm(session, "count");
if (parm != NULL)
{
count = (uint16_t)parm->value.unumber;
}
bcmcli_session_print(
session,
"Sending %u proxy packet%s to %u ONU%s...\n",
count,
count == 1 ? "" : "s",
onu_count,
onu_count == 1 ? "" : "s");
/* call the proxy API (potentially several times) for each ONU */
for (onu_idx = 0; onu_idx < onu_count; onu_idx++)
{
bcmolt_gpon_onu_key onu_key = { .pon_ni = pon_ni, .onu_id = onus[onu_idx] };
bcmolt_u8_list_u32_max_2048 buffer = { .val = saved_packet };
bcmolt_gpon_onu_cpu_packets proxy;
uint16_t packets_per_proxy;
/* build the proxy API message, except the buffer/number of packets */
BCMOLT_PROXY_INIT(&proxy, gpon_onu, cpu_packets, onu_key);
BCMOLT_PROXY_PROP_SET(&proxy, gpon_onu, cpu_packets, packet_type, saved_packet_type);
BCMOLT_PROXY_PROP_SET(&proxy, gpon_onu, cpu_packets, calc_crc, saved_packet_calc_crc);
BCMOLT_PROXY_PROP_SET(&proxy, gpon_onu, cpu_packets, packet_size, saved_packet_len);
/* calculate the number of packets we can fit per invocation of the proxy API */
packets_per_proxy = MIN(count, 2048 / saved_packet_len);
BCMOLT_PROXY_PROP_SET(&proxy, gpon_onu, cpu_packets, number_of_packets, packets_per_proxy);
/* prepare the buffer data with several copies of the same packet in a row */
for (i = 1; i < packets_per_proxy; i++)
{
memcpy(&saved_packet[i * saved_packet_len], saved_packet, saved_packet_len);
}
/* call the proxy API enough times to send the requested number of packets */
for (i = 0; i < count; i += packets_per_proxy)
{
uint16_t number_of_packets = MIN(packets_per_proxy, count - i);
BCMOLT_PROXY_PROP_SET(&proxy, gpon_onu, cpu_packets, number_of_packets, number_of_packets);
buffer.len = number_of_packets * saved_packet_len;
BCMOLT_PROXY_PROP_SET(&proxy, gpon_onu, cpu_packets, buffer, buffer);
err = bcmolt_proxy_send(device, &proxy.hdr);
if (err != BCM_ERR_OK)
{
bcmcli_session_print(
session,
"[Error] proxy send: ONU %u packet index %u: %s\n",
onus[onu_idx],
i,
bcmos_strerror(err));
return err;
}
}
}
bcmcli_session_print(session, "%u proxy packet%s sent successfully!\n", count, count == 1 ? "" : "s");
return BCM_ERR_OK;
}
static bcmos_errno send_packet_to_xgpon_onu_list(bcmcli_session *session, uint16_t onu_count, bcmolt_xgpon_onu_id *onus)
{
uint16_t count = 1;
uint16_t i;
uint16_t onu_idx;
bcmos_errno err;
bcmcli_cmd_parm *parm;
bcmolt_devid device = (bcmolt_devid)bcmcli_find_named_parm(session, "device")->value.unumber;
bcmolt_pon_ni pon_ni = (bcmolt_pon_ni)bcmcli_find_named_parm(session, "pon_ni")->value.unumber;
if (saved_packet_len == 0)
{
bcmcli_session_print(session, "[Error] you must build/save a packet before you can send it\n");
return BCM_ERR_PARM;
}
parm = bcmcli_find_named_parm(session, "count");
if (parm != NULL)
{
count = (uint16_t)parm->value.unumber;
}
bcmcli_session_print(
session,
"Sending %u proxy packet%s to %u ONU%s...\n",
count,
count == 1 ? "" : "s",
onu_count,
onu_count == 1 ? "" : "s");
/* call the proxy API (potentially several times) for each ONU */
for (onu_idx = 0; onu_idx < onu_count; onu_idx++)
{
bcmolt_xgpon_onu_key onu_key = { .pon_ni = pon_ni, .onu_id = onus[onu_idx] };
bcmolt_u8_list_u32_max_2048 buffer = { .val = saved_packet };
bcmolt_xgpon_onu_cpu_packets proxy;
uint16_t packets_per_proxy;
/* build the proxy API message, except the buffer/number of packets */
BCMOLT_PROXY_INIT(&proxy, xgpon_onu, cpu_packets, onu_key);
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_onu, cpu_packets, packet_type, saved_packet_type);
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_onu, cpu_packets, calc_crc, saved_packet_calc_crc);
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_onu, cpu_packets, packet_size, saved_packet_len);
/* calculate the number of packets we can fit per invocation of the proxy API */
packets_per_proxy = MIN(count, 2048 / saved_packet_len);
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_onu, cpu_packets, number_of_packets, packets_per_proxy);
/* prepare the buffer data with several copies of the same packet in a row */
for (i = 1; i < packets_per_proxy; i++)
{
memcpy(&saved_packet[i * saved_packet_len], saved_packet, saved_packet_len);
}
/* call the proxy API enough times to send the requested number of packets */
for (i = 0; i < count; i += packets_per_proxy)
{
uint16_t number_of_packets = MIN(packets_per_proxy, count - i);
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_onu, cpu_packets, number_of_packets, number_of_packets);
buffer.len = number_of_packets * saved_packet_len;
BCMOLT_PROXY_PROP_SET(&proxy, xgpon_onu, cpu_packets, buffer, buffer);
err = bcmolt_proxy_send(device, &proxy.hdr);
if (err != BCM_ERR_OK)
{
bcmcli_session_print(
session,
"[Error] proxy send: ONU %u packet index %u: %s\n",
onus[onu_idx],
i,
bcmos_strerror(err));
return err;
}
}
}
bcmcli_session_print(session, "%u proxy packet%s sent successfully!\n", count, count == 1 ? "" : "s");
return BCM_ERR_OK;
}
static bcmos_errno send_to_onu_cb(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
{
bcmcli_cmd_parm *onu_parm = bcmcli_find_named_parm(session, "onu");
bcmolt_pon_ni pon_id = (bcmolt_pon_ni)bcmcli_find_named_parm(session, "pon_ni")->value.unumber;
uint16_t i;
pon_mode mode = pon_mode_get(pon_id);
if (mode == PON_MODE_GPON)
{
static bcmolt_gpon_onu_id onu_id_buf[MAX_ONUS_FOR_SEND];
for (i = 0; i < onu_parm->array_size; i++)
{
onu_id_buf[i] = (bcmolt_gpon_onu_id)onu_parm->values[i].unumber;
}
return send_packet_to_gpon_onu_list(session, (uint16_t)onu_parm->array_size, onu_id_buf);
}
else if (mode == PON_MODE_XGPON)
{
static bcmolt_xgpon_onu_id onu_id_buf[MAX_ONUS_FOR_SEND];
for (i = 0; i < onu_parm->array_size; i++)
{
onu_id_buf[i] = (bcmolt_xgpon_onu_id)onu_parm->values[i].unumber;
}
return send_packet_to_xgpon_onu_list(session, (uint16_t)onu_parm->array_size, onu_id_buf);
}
else
{
bcmcli_session_print(session, "[Error] Invalid system mode\n");
return BCM_ERR_STATE;
}
}
static void dump_saved_mac(bcmcli_session *session, uint16_t offset)
{
uint16_t i;
for (i = 0; i < 6; i++)
{
if (i != 0)
{
bcmcli_session_print(session, ":");
}
bcmcli_session_print(session, "%02X", saved_packet[offset + i]);
}
}
static bcmos_errno dump_packet_cb(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
{
uint16_t i;
uint16_t data_offset;
if (saved_packet_len == 0)
{
bcmcli_session_print(session, "No packet has been built yet\n");
return BCM_ERR_OK;
}
bcmcli_session_print(session, "Saved packet parameters:\n");
bcmcli_session_print(session, " Type: %s\n", saved_packet_type == BCMOLT_PACKET_TYPE_CPU ? "CPU" : "OMCI");
bcmcli_session_print(session, " Length: %u\n", saved_packet_len);
bcmcli_session_print(session, " Auto-calculate CRC: %s\n", saved_packet_calc_crc ? "yes" : "no");
if (saved_packet_type == BCMOLT_PACKET_TYPE_CPU)
{
bcmcli_session_print(session, " Ethernet DA: ");
dump_saved_mac(session, 0);
bcmcli_session_print(session, "\n");
bcmcli_session_print(session, " Ethernet SA: ");
dump_saved_mac(session, 6);
bcmcli_session_print(session, "\n");
bcmcli_session_print(session, " EtherType: 0x%02X%02X\n", saved_packet[12], saved_packet[13]);
data_offset = 14;
}
else
{
data_offset = 0;
}
bcmcli_session_print(session, "Data bytes (starting at offset %u):", data_offset);
for (i = data_offset; i < saved_packet_len; i++)
{
if ((i - data_offset) % 16 == 0)
{
bcmcli_session_print(session, "\n ");
}
else
{
bcmcli_session_print(session, " ");
}
bcmcli_session_print(session, "%02X", saved_packet[i]);
}
bcmcli_session_print(session, "\n");
return BCM_ERR_OK;
}
bcmos_errno bcmolt_user_appl_gpon_utils_init(bcmcli_entry *top_dir)
{
bcmos_errno err = BCM_ERR_OK;
if (!gpon_utils_is_registered)
{
gpon_utils_is_registered = BCMOS_TRUE;
/* Subscribe for device change indication */
err = bcmolt_dev_sel_ind_register(bcmolt_user_appl_gpon_utils_device_change_ind);
}
return err ? err : bcmolt_user_appl_gpon_utils_create(top_dir);
}
static bcmos_errno bcmolt_user_appl_gpon_utils_create(bcmcli_entry *top_dir)
{
static bcmcli_enum_val generated_packet_pattern_table[] =
{
{ .name = "byte_cycle", .val = GENERATED_PACKET_PATTERN_BYTE_CYCLE },
{ .name = "word_cycle", .val = GENERATED_PACKET_PATTERN_WORD_CYCLE },
{ .name = "const", .val = GENERATED_PACKET_PATTERN_CONST },
BCMCLI_ENUM_LAST
};
static bcmcli_parm_value gem_port_ids[MAX_GEM_PORTS_FOR_SEND];
static bcmcli_parm_value onu_ids[MAX_ONUS_FOR_SEND];
bcmcli_entry *dir;
if (bcmcli_dir_find(top_dir, "gpon"))
{
return BCM_ERR_OK;
}
gpon_utils_cli_dir_cli_destroy();
dir = bcmcli_dir_add(top_dir, "gpon", "Common GPON/XGPON functions", BCMCLI_ACCESS_ADMIN, NULL);
BCMOS_CHECK_RETURN_ERROR(!dir, BCM_ERR_NOMEM);
BCMCLI_MAKE_CMD(
dir,
"build_cpu_packet",
"Build and save CPU packet",
build_cpu_packet_cb,
BCMCLI_MAKE_PARM_ENUM("calc_crc", "Auto-calculate CRC", bcmcli_enum_bool_table, BCMCLI_PARM_FLAG_NONE),
BCMCLI_MAKE_PARM_RANGE(
"packet_size", "Full packet size", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_NONE, 0, MAX_PACKET_SIZE),
BCMCLI_MAKE_PARM_ENUM("pattern", "Background pattern", generated_packet_pattern_table, BCMCLI_PARM_FLAG_NONE),
BCMCLI_MAKE_PARM_RANGE("const_value", "Const value", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_NONE, 0, 0xFF),
BCMCLI_MAKE_PARM("eth_da", "Ethernet destination address", BCMCLI_PARM_MAC, BCMCLI_PARM_FLAG_NONE),
BCMCLI_MAKE_PARM("eth_sa", "Ethernet source address", BCMCLI_PARM_MAC, BCMCLI_PARM_FLAG_NONE));
BCMCLI_MAKE_CMD(
dir,
"build_omci_packet",
"Build and save OMCI packet",
build_omci_packet_cb,
BCMCLI_MAKE_PARM_ENUM("calc_crc", "Auto-calculate CRC", bcmcli_enum_bool_table, BCMCLI_PARM_FLAG_NONE),
BCMCLI_MAKE_PARM_RANGE(
"packet_size", "Full packet size", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_NONE, 0, MAX_PACKET_SIZE),
BCMCLI_MAKE_PARM_ENUM("pattern", "Background pattern", generated_packet_pattern_table, BCMCLI_PARM_FLAG_NONE),
BCMCLI_MAKE_PARM_RANGE("const_value", "Const value", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_NONE, 0, 0xFF));
BCMCLI_MAKE_CMD(
dir,
"send_to_gem",
"Send saved CPU/OMCI packet to GEM port(s)",
send_to_gem_cb,
BCMCLI_MAKE_PARM("device", "Device ID", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_NONE),
BCMCLI_MAKE_PARM("pon_ni", "PON NI", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_NONE),
BCMCLI_MAKE_PARM_ARRAY(
"gem",
"GEM port IDs, comma separated",
BCMCLI_PARM_UNUMBER,
BCMCLI_PARM_FLAG_NONE,
MAX_GEM_PORTS_FOR_SEND,
gem_port_ids),
BCMCLI_MAKE_PARM("count", "Number of packets (default 1)", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_OPTIONAL));
BCMCLI_MAKE_CMD(
dir,
"send_to_onu",
"Send saved CPU/OMCI packet to ONU(s) (OMCI GEM port)",
send_to_onu_cb,
BCMCLI_MAKE_PARM("device", "Device ID", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_NONE),
BCMCLI_MAKE_PARM("pon_ni", "PON NI", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_NONE),
BCMCLI_MAKE_PARM_ARRAY(
"onu",
"ONU IDs, comma separated",
BCMCLI_PARM_UNUMBER,
BCMCLI_PARM_FLAG_NONE,
MAX_ONUS_FOR_SEND,
onu_ids),
BCMCLI_MAKE_PARM("count", "Number of packets (default 1)", BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_OPTIONAL));
BCMCLI_MAKE_CMD_NOPARM(
dir,
"dump_packet",
"Print saved CPU/OMCI packet data",
dump_packet_cb);
gpon_utils_cli_dir = dir;
gpon_utils_cli_top_dir = top_dir;
return BCM_ERR_OK;
}