blob: adaba1a92cec94a608f3051fb116522e9cccda02 [file] [log] [blame]
/*
** Copyright 2017-present Open Networking Foundation
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdio.h>
#include <bal_api.h>
#undef _SYS_QUEUE_H_
#include "asfvolt16_driver.h"
#include "bal_flow_hdlr.h"
/********************************************************************\
* Function : bal_fill_queue_cfg *
* Description : copy queue information from proto structure to *
* BAL structure *
********************************************************************/
static uint32_t bal_fill_queue_cfg(BalTmQueueRef *tmp_que,
bcmbal_tm_queue_ref *que_val)
{
if(tmp_que->has_sched_id)
{
que_val->sched_id = tmp_que->sched_id;
ASFVOLT_LOG(ASFVOLT_DEBUG, "que_val->sched_id = %d", que_val->sched_id);
}
if(tmp_que->has_queue_id)
{
que_val->queue_id = tmp_que->queue_id;
ASFVOLT_LOG(ASFVOLT_DEBUG, "que_val->queue_id = %d", que_val->queue_id);
}
return BAL_ERRNO__BAL_ERR_OK;
}
/********************************************************************\
* Function : bal_fill_action_cfg *
* Description : copy action information from proto structure to *
* BAL structure *
********************************************************************/
static uint32_t bal_fill_action_cfg(BalAction *tmp_action,
bcmbal_action *action_val)
{
if(tmp_action->has_presence_mask)
{
action_val->presence_mask = tmp_action->presence_mask;
if (action_val->presence_mask & BCMBAL_ACTION_ID_CMDS_BITMASK)
{
action_val->cmds_bitmask = tmp_action->cmds_bitmask;
ASFVOLT_LOG(ASFVOLT_DEBUG, "action_val->cmds_bitmask = %x", action_val->cmds_bitmask);
}
if (action_val->presence_mask & BCMBAL_ACTION_ID_O_VID)
{
action_val->o_vid = tmp_action->o_vid;
ASFVOLT_LOG(ASFVOLT_DEBUG, "action_val->o_vid = %d", action_val->o_vid);
}
if (action_val->presence_mask & BCMBAL_ACTION_ID_O_PBITS)
{
action_val->o_pbits = tmp_action->o_pbits;
ASFVOLT_LOG(ASFVOLT_DEBUG, "action_val->o_pbits = %d", action_val->o_pbits);
}
if (action_val->presence_mask & BCMBAL_ACTION_ID_O_TPID)
{
action_val->o_tpid = tmp_action->o_tpid;
ASFVOLT_LOG(ASFVOLT_DEBUG, "action_val->o_tpid = %d", action_val->o_tpid);
}
if (action_val->presence_mask & BCMBAL_ACTION_ID_I_VID)
{
action_val->i_vid = tmp_action->i_vid;
ASFVOLT_LOG(ASFVOLT_DEBUG, "action_val->i_vid = %d", action_val->i_vid);
}
if (action_val->presence_mask & BCMBAL_ACTION_ID_I_PBITS)
{
action_val->i_pbits = tmp_action->i_pbits;
ASFVOLT_LOG(ASFVOLT_DEBUG, "action_val->i_pbits = %d", action_val->i_pbits);
}
if (action_val->presence_mask & BCMBAL_ACTION_ID_I_TPID)
{
action_val->i_tpid = tmp_action->i_tpid;
ASFVOLT_LOG(ASFVOLT_DEBUG, "action_val->i_tpid = %d", action_val->i_tpid);
}
ASFVOLT_LOG(ASFVOLT_DEBUG, "action_val->presence_mask = %x", action_val->presence_mask);
}
else
{
ASFVOLT_LOG(ASFVOLT_ERROR, "Action is not present in the flow");
return BAL_ERRNO__BAL_ERR_PARM;
}
return BAL_ERRNO__BAL_ERR_OK;
}
/********************************************************************\
* Function : bal_fill_classifier_cfg *
* Description : copy classifier information from proto structure to*
* BAL structure
********************************************************************/
uint32_t bal_fill_classifier_cfg(BalClassifier *tmp_classifier,
bcmbal_classifier *classifier_val)
{
if(tmp_classifier->has_presence_mask)
{
classifier_val->presence_mask = tmp_classifier->presence_mask;
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_O_TPID)
{
classifier_val->o_tpid = tmp_classifier->o_tpid;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->o_tpid = %d", classifier_val->o_tpid);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_O_VID)
{
classifier_val->o_vid = tmp_classifier->o_vid;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->o_vid = %d", classifier_val->o_vid);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_I_TPID)
{
classifier_val->i_tpid = tmp_classifier->i_tpid;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->i_tpid = %d", classifier_val->i_tpid);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_I_VID)
{
classifier_val->i_vid = tmp_classifier->i_vid;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->i_vid = %d", classifier_val->i_vid);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_O_PBITS)
{
classifier_val->o_pbits = tmp_classifier->o_pbits;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->o_pbits = %d", classifier_val->o_pbits);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_I_PBITS)
{
classifier_val->i_pbits = tmp_classifier->i_pbits;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->i_pbits = %d", classifier_val->i_pbits);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_ETHER_TYPE)
{
classifier_val->ether_type = tmp_classifier->ether_type;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->ether_type = %x", classifier_val->ether_type);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_DST_MAC)
{
if(tmp_classifier->dst_mac.len > BCMOS_ETH_ALEN)
{
memcpy(classifier_val->dst_mac.u8,
tmp_classifier->dst_mac.data, tmp_classifier->dst_mac.len);
/*ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->dst_mac= %d", classifier_val->dst_mac);*/
}
else
{
ASFVOLT_LOG(ASFVOLT_ERROR, "dst_mac should not be more than 6 bytes."
"actual bytes %lu", tmp_classifier->dst_mac.len);
return BAL_ERRNO__BAL_ERR_PARM;
}
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_SRC_MAC)
{
if(tmp_classifier->src_mac.len > BCMOS_ETH_ALEN)
{
memcpy(classifier_val->src_mac.u8,
tmp_classifier->src_mac.data, tmp_classifier->src_mac.len);
/*ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->src_mac= %x", classifier_val->src_mac);*/
}
else
{
ASFVOLT_LOG(ASFVOLT_ERROR, "src_mac should not be more than 6 bytes."
"actual bytes %lu", tmp_classifier->src_mac.len);
return BAL_ERRNO__BAL_ERR_PARM;
}
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_IP_PROTO)
{
classifier_val->ip_proto = tmp_classifier->ip_proto;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->ip_proto = %x", classifier_val->ip_proto);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_DST_IP)
{
classifier_val->dst_ip.u32 = tmp_classifier->dst_ip;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->dst_ip = %x", classifier_val->dst_ip.u32);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_SRC_IP)
{
classifier_val->src_ip.u32 = tmp_classifier->src_ip;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->src_ip = %x", classifier_val->src_ip.u32);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_SRC_PORT)
{
classifier_val->src_port = tmp_classifier->src_port;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->src_port = %d", classifier_val->src_port);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_DST_PORT)
{
classifier_val->dst_port = tmp_classifier->dst_port;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->dst_port = %d", classifier_val->dst_port);
}
if (classifier_val->presence_mask & BCMBAL_CLASSIFIER_ID_PKT_TAG_TYPE)
{
classifier_val->pkt_tag_type = tmp_classifier->pkt_tag_type;
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->pkt_tag_type = %x", classifier_val->pkt_tag_type);
}
ASFVOLT_LOG(ASFVOLT_DEBUG, "classifier_val->presence_mask = %x", classifier_val->presence_mask);
}
else
{
ASFVOLT_LOG(ASFVOLT_ERROR, "Classifier is not present in the flow");
return BAL_ERRNO__BAL_ERR_PARM;
}
return BAL_ERRNO__BAL_ERR_OK;
}
/********************************************************************\
* Function : bal_flow_cfg_req *
* Description : Configure the the OLT DEVICE with flow information *
* using BAL Apis *
********************************************************************/
uint32_t bal_flow_cfg_set(BalFlowCfg *flow_cfg)
{
bcmos_errno err = BCM_ERR_OK;
BalErrno bal_err = BAL_ERRNO__BAL_ERR_OK;
bcmbal_flow_cfg cfg; /**< declare main API struct */
bcmbal_flow_key key = { 0, 0}; /**< declare key */
bcmbal_classifier classifier_value = {};
bcmbal_action action_value = {};
bcmbal_tm_queue_ref queue_value = {};
/* build key from CLI parameters */
if(flow_cfg->key->has_flow_id)
{
key.flow_id = (bcmbal_flow_id) flow_cfg->key->flow_id;
}
else
{
ASFVOLT_LOG(ASFVOLT_ERROR, "Invalid Flow Id (%d)", flow_cfg->key->flow_id);
return BAL_ERRNO__BAL_ERR_PARM;
}
ASFVOLT_LOG(ASFVOLT_INFO, "Adding the flow to OLT. FlowID(%d)", flow_cfg->key->flow_id);
if (!flow_cfg->key->has_flow_type &&
((flow_cfg->key->flow_type < BAL_FLOW_TYPE__BAL_FLOW_TYPE_UPSTREAM) ||
flow_cfg->key->flow_type > BAL_FLOW_TYPE__BAL_FLOW_TYPE_MULTICAST ))
{
ASFVOLT_LOG(ASFVOLT_ERROR, "Flow type is not supported (%d)", flow_cfg->key->flow_type);
return BAL_ERRNO__BAL_ERR_PARM;
}
else
{
ASFVOLT_LOG(ASFVOLT_DEBUG, "flow_type = %d", flow_cfg->key->flow_type);
key.flow_type = (bcmbal_flow_type) flow_cfg->key->flow_type;
}
/* init the API struct */
BCMBAL_CFG_INIT(&cfg, flow, key);
/* decode API parameters from grpc-c */
/* Admin State */
ASFVOLT_CFG_PROP_SET(cfg, flow, admin_state,
flow_cfg->data->has_admin_state,
flow_cfg->data->admin_state);
ASFVOLT_LOG(ASFVOLT_DEBUG, "admin state = %d", flow_cfg->data->admin_state);
/* Operational status */
ASFVOLT_CFG_PROP_SET(cfg, flow, oper_status,
flow_cfg->data->has_oper_status,
flow_cfg->data->oper_status);
ASFVOLT_LOG(ASFVOLT_DEBUG, "Oper. status = %d", flow_cfg->data->oper_status);
/* Access Side interface ID */
ASFVOLT_CFG_PROP_SET(cfg, flow, access_int_id,
BCMOS_TRUE,
flow_cfg->data->access_int_id);
ASFVOLT_LOG(ASFVOLT_DEBUG, "access_int_id = %d", flow_cfg->data->access_int_id);
/* Network interface ID */
ASFVOLT_CFG_PROP_SET(cfg, flow, network_int_id,
BCMOS_TRUE,
flow_cfg->data->network_int_id);
ASFVOLT_LOG(ASFVOLT_DEBUG, "network_int_id = %d", flow_cfg->data->network_int_id);
/* ONU ID */
if(BAL_FLOW_TYPE__BAL_FLOW_TYPE_MULTICAST != flow_cfg->key->flow_type)
{
ASFVOLT_CFG_PROP_SET(cfg, flow, sub_term_id,
flow_cfg->data->has_sub_term_id,
flow_cfg->data->sub_term_id);
ASFVOLT_LOG(ASFVOLT_DEBUG, "sub_term_id = %d", flow_cfg->data->sub_term_id);
}
else if (BAL_FLOW_TYPE__BAL_FLOW_TYPE_MULTICAST == flow_cfg->key->flow_type)
{
/* In case of Multicast the flow belongs to particular group */
ASFVOLT_CFG_PROP_SET(cfg, flow, group_id,
flow_cfg->data->has_group_id,
flow_cfg->data->group_id);
ASFVOLT_LOG(ASFVOLT_DEBUG, "group_id = %d", flow_cfg->data->group_id);
}
/*Subscriber Terminal UNI index*/
ASFVOLT_CFG_PROP_SET(cfg, flow, sub_term_uni_idx,
flow_cfg->data->has_sub_term_uni_idx,
flow_cfg->data->sub_term_uni_idx);
ASFVOLT_LOG(ASFVOLT_DEBUG, "sub_term_uni_idx = %d", flow_cfg->data->sub_term_uni_idx);
/*Resolve MAC*/
ASFVOLT_CFG_PROP_SET(cfg, flow, resolve_mac,
flow_cfg->data->has_resolve_mac,
flow_cfg->data->resolve_mac);
ASFVOLT_LOG(ASFVOLT_DEBUG, "resolve_mac = %d", flow_cfg->data->resolve_mac);
/*Gem port*/
ASFVOLT_CFG_PROP_SET(cfg, flow, svc_port_id,
flow_cfg->data->has_svc_port_id,
flow_cfg->data->svc_port_id);
ASFVOLT_LOG(ASFVOLT_DEBUG, "svc_port_id = %d", flow_cfg->data->svc_port_id);
/*priority*/
ASFVOLT_CFG_PROP_SET(cfg, flow, priority,
flow_cfg->data->has_priority,
flow_cfg->data->priority);
ASFVOLT_LOG(ASFVOLT_DEBUG, "priority = %d",flow_cfg->data->priority);
BalClassifier *tmp_classifier = (BalClassifier*)(flow_cfg->data->classifier);
if (tmp_classifier != NULL)
{
bal_err = bal_fill_classifier_cfg(tmp_classifier, &classifier_value);
if(bal_err != BAL_ERRNO__BAL_ERR_OK)
{
ASFVOLT_LOG(ASFVOLT_ERROR,
"Addition of flow %d failed while processing classifier",
flow_cfg->key->flow_id);
return bal_err;
}
ASFVOLT_CFG_PROP_SET(cfg, flow, classifier, BCMOS_TRUE, classifier_value);
}
else
{
ASFVOLT_LOG(ASFVOLT_DEBUG, "No Classifier for flow");
}
BalAction *tmp_action = (BalAction*)(flow_cfg->data->action);
if (tmp_action != NULL)
{
bal_err = bal_fill_action_cfg(tmp_action, &action_value);
if(bal_err != BAL_ERRNO__BAL_ERR_OK)
{
ASFVOLT_LOG(ASFVOLT_ERROR,
"Addition of flow %d failed while processing action",
flow_cfg->key->flow_id);
return bal_err;
}
ASFVOLT_CFG_PROP_SET(cfg, flow, action, BCMOS_TRUE, action_value);
}
else
{
ASFVOLT_LOG(ASFVOLT_DEBUG, "No Action for flow");
}
/*cookie*/
ASFVOLT_CFG_PROP_SET(cfg, flow, cookie,
flow_cfg->data->has_cookie,
flow_cfg->data->cookie);
ASFVOLT_LOG(ASFVOLT_DEBUG, "priority = %lx",flow_cfg->data->cookie);
/*Egress queue*/
BalTmQueueRef *tmp_que = (BalTmQueueRef*)(flow_cfg->data->queue);
if (tmp_que != NULL)
{
bal_err = bal_fill_queue_cfg(tmp_que, &queue_value);
if(bal_err != BAL_ERRNO__BAL_ERR_OK)
{
ASFVOLT_LOG(ASFVOLT_ERROR,
"Addition of flow %d failed while processing queue",
flow_cfg->key->flow_id);
return bal_err;
}
ASFVOLT_CFG_PROP_SET(cfg, flow, queue, BCMOS_TRUE, queue_value);
}
else
{
ASFVOLT_LOG(ASFVOLT_DEBUG, "No queue Information for flow");
}
/*dba_tm_sched_id*/
ASFVOLT_CFG_PROP_SET(cfg, flow, dba_tm_sched_id,
flow_cfg->data->has_dba_tm_sched_id,
flow_cfg->data->dba_tm_sched_id);
ASFVOLT_LOG(ASFVOLT_DEBUG, "tm_sched used for dba = %d",flow_cfg->data->dba_tm_sched_id);
err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &cfg.hdr);
if(err != BCM_ERR_OK)
{
ASFVOLT_LOG(ASFVOLT_ERROR,
"Failed to configure the flow. FlowId(%d)", key.flow_id);
return BAL_ERRNO__BAL_ERR_INTERNAL;
}
return BAL_ERRNO__BAL_ERR_OK;
}
/********************************************************************\
* Function : bal_flow_cfg_clear *
* Description : Deletes/Clears the OLT DEVICE with flow *
* information using BAL Apis *
********************************************************************/
uint32_t bal_flow_cfg_clear(BalFlowKey *flow_key)
{
bcmos_errno err = BCM_ERR_OK;
bcmbal_flow_cfg cfg; /**< declare main API struct */
bcmbal_flow_key key = { }; /**< declare key */
if (flow_key->has_flow_id && flow_key->has_flow_type)
{
key.flow_id = flow_key->flow_id;
key.flow_type = flow_key->flow_type;
}
else
{
ASFVOLT_LOG(ASFVOLT_DEBUG, "Invalid Flow Parameters to clear FlowId(%d), FlowType(%d)",
key.flow_id, key.flow_type);
return BAL_ERRNO__BAL_ERR_PARM;
}
ASFVOLT_LOG(ASFVOLT_DEBUG, "FlowId(%d), FlowType(%d)", key.flow_id, key.flow_type);
/* init the API struct */
BCMBAL_CFG_INIT(&cfg, flow, key);
/* call API */
err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &cfg.hdr);
if( err != BCM_ERR_OK)
{
ASFVOLT_LOG(ASFVOLT_INFO,
"Failed to clear the Flow. FlowID(%d) FlowType(%d)",
key.flow_id, key.flow_type);
return BAL_ERRNO__BAL_ERR_INTERNAL;
}
return BAL_ERRNO__BAL_ERR_OK;
}
/********************************************************************\
* Function : bal_flow_cfg_get *
* Description : Get flow information from BAL. *
********************************************************************/
uint32_t bal_flow_cfg_get(BalFlowKey *flow_key, BalFlowCfg *flow_cfg)
{
bcmos_errno err = BCM_ERR_OK;
bcmbal_flow_cfg cfg; /**< declare main API struct */
bcmbal_flow_key key = { }; /**< declare key */
if (flow_key->has_flow_id && flow_key->has_flow_type)
{
key.flow_id = flow_key->flow_id;
key.flow_type = flow_key->flow_type;
}
else
{
ASFVOLT_LOG(ASFVOLT_DEBUG, "Invalid Flow Parameters to get cfg FlowId(%d), FlowType(%d)",
key.flow_id, key.flow_type);
return BAL_ERRNO__BAL_ERR_PARM;
}
/* init the API struct */
BCMBAL_CFG_INIT(&cfg, flow, key);
BCMBAL_CFG_PROP_GET(&cfg, flow, all_properties);
/* call API */
err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &cfg.hdr);
if( err != BCM_ERR_OK)
{
ASFVOLT_LOG(ASFVOLT_INFO,
"Failed to get Flow Info. FlowID(%d) FlowType(%d)",
key.flow_id, key.flow_type);
return BAL_ERRNO__BAL_ERR_INTERNAL;
}
ASFVOLT_LOG(ASFVOLT_INFO,
"To-Do. Send Flow details to Adapter");
return BAL_ERRNO__BAL_ERR_OK;
}