mirror of
https://github.com/Telecominfraproject/ols-ucentral-client.git
synced 2025-10-29 00:52:33 +00:00
Merge pull request #5 from Telecominfraproject/plv_next_270224
Plv next 270224
This commit is contained in:
@@ -41,6 +41,7 @@ extern "C" {
|
||||
*/
|
||||
#define PID_TO_NAME(p, name) sprintf(name, "Ethernet%hu", p)
|
||||
#define NAME_TO_PID(p, name) sscanf((name), "Ethernet%hu", (p))
|
||||
#define VLAN_TO_NAME(v, name) sprintf((name), "Vlan%hu", (v))
|
||||
|
||||
struct plat_vlan_memberlist;
|
||||
struct plat_port_vlan;
|
||||
@@ -64,6 +65,18 @@ enum plat_ieee8021x_port_host_mode {
|
||||
PLAT_802_1X_PORT_HOST_MODE_SINGLE_HOST,
|
||||
};
|
||||
|
||||
enum plat_ieee8021x_das_auth_type {
|
||||
PLAT_802_1X_DAS_AUTH_TYPE_ANY,
|
||||
PLAT_802_1X_DAS_AUTH_TYPE_ALL,
|
||||
PLAT_802_1X_DAS_AUTH_TYPE_SESSION_KEY,
|
||||
};
|
||||
|
||||
enum plat_igmp_version {
|
||||
PLAT_IGMP_VERSION_1,
|
||||
PLAT_IGMP_VERSION_2,
|
||||
PLAT_IGMP_VERSION_3
|
||||
};
|
||||
|
||||
#define UCENTRAL_PORT_LLDP_PEER_INFO_MAX_MGMT_IPS (2)
|
||||
/* Interface LLDP peer's data, as defined in interface.lldp.yml*/
|
||||
struct plat_port_lldp_peer_info {
|
||||
@@ -252,10 +265,27 @@ struct plat_port_l2 {
|
||||
struct plat_ipv4 ipv4;
|
||||
};
|
||||
|
||||
struct plat_igmp {
|
||||
bool exist;
|
||||
bool snooping_enabled;
|
||||
bool querier_enabled;
|
||||
bool fast_leave_enabled;
|
||||
uint32_t query_interval;
|
||||
uint32_t last_member_query_interval;
|
||||
uint32_t max_response_time;
|
||||
enum plat_igmp_version version;
|
||||
size_t num_groups;
|
||||
struct {
|
||||
struct in_addr addr;
|
||||
struct plat_ports_list *egress_ports_list;
|
||||
} *groups;
|
||||
};
|
||||
|
||||
struct plat_port_vlan {
|
||||
struct plat_vlan_memberlist *members_list_head;
|
||||
struct plat_ipv4 ipv4;
|
||||
struct plat_dhcp dhcp;
|
||||
struct plat_igmp igmp;
|
||||
uint16_t id;
|
||||
uint16_t mstp_instance;
|
||||
};
|
||||
@@ -282,6 +312,18 @@ struct plat_syslog_cfg {
|
||||
char host[SYSLOG_CFG_FIELD_STR_MAX_LEN];
|
||||
};
|
||||
|
||||
struct plat_enabled_service_cfg {
|
||||
struct {
|
||||
bool enabled;
|
||||
} ssh;
|
||||
struct telnet {
|
||||
bool enabled;
|
||||
} telnet;
|
||||
struct {
|
||||
bool enabled;
|
||||
} http;
|
||||
};
|
||||
|
||||
struct plat_rtty_cfg {
|
||||
char id[RTTY_CFG_FIELD_STR_MAX_LEN];
|
||||
char passwd[RTTY_CFG_FIELD_STR_MAX_LEN];
|
||||
@@ -376,6 +418,31 @@ struct plat_radius_hosts_list {
|
||||
struct plat_radius_host host;
|
||||
};
|
||||
|
||||
struct plat_ieee8021x_dac_host {
|
||||
char hostname[RADIUS_CFG_HOSTNAME_STR_MAX_LEN];
|
||||
char passkey[RADIUS_CFG_PASSKEY_STR_MAX_LEN];
|
||||
};
|
||||
|
||||
struct plat_ieee8021x_dac_list {
|
||||
struct plat_ieee8021x_dac_list *next;
|
||||
struct plat_ieee8021x_dac_host host;
|
||||
};
|
||||
|
||||
struct plat_port_isolation_session_ports {
|
||||
struct plat_ports_list *ports_list;
|
||||
};
|
||||
|
||||
struct plat_port_isolation_session {
|
||||
uint64_t id;
|
||||
struct plat_port_isolation_session_ports uplink;
|
||||
struct plat_port_isolation_session_ports downlink;
|
||||
};
|
||||
|
||||
struct plat_port_isolation_cfg {
|
||||
struct plat_port_isolation_session *sessions;
|
||||
size_t sessions_num;
|
||||
};
|
||||
|
||||
struct plat_cfg {
|
||||
struct plat_unit unit;
|
||||
/* Alloc all ports, but access them only if bit is set. */
|
||||
@@ -385,6 +452,7 @@ struct plat_cfg {
|
||||
BITMAP_DECLARE(vlans_to_cfg, MAX_VLANS);
|
||||
struct plat_metrics_cfg metrics;
|
||||
struct plat_syslog_cfg *log_cfg;
|
||||
struct plat_enabled_service_cfg enabled_services_cfg;
|
||||
/* Port's interfaces (provide l2 iface w/o bridge caps) */
|
||||
struct plat_port_l2 portsl2[MAX_NUM_OF_PORTS];
|
||||
struct ucentral_router router;
|
||||
@@ -393,7 +461,17 @@ struct plat_cfg {
|
||||
/* Instance zero is for global instance (like common values in rstp) */
|
||||
struct plat_stp_instance_cfg stp_instances[MAX_VLANS];
|
||||
struct plat_radius_hosts_list *radius_hosts_list;
|
||||
bool ieee8021x_is_auth_ctrl_enabled;
|
||||
struct {
|
||||
bool is_auth_ctrl_enabled;
|
||||
bool bounce_port_ignore;
|
||||
bool disable_port_ignore;
|
||||
bool ignore_server_key;
|
||||
bool ignore_session_key;
|
||||
char server_key[RADIUS_CFG_PASSKEY_STR_MAX_LEN];
|
||||
enum plat_ieee8021x_das_auth_type das_auth_type;
|
||||
struct plat_ieee8021x_dac_list *das_dac_list;
|
||||
} ieee8021x;
|
||||
struct plat_port_isolation_cfg port_isolation_cfg;
|
||||
};
|
||||
|
||||
struct plat_learned_mac_addr {
|
||||
@@ -503,15 +581,57 @@ enum {
|
||||
PLAT_REBOOT_CAUSE_UNAVAILABLE,
|
||||
};
|
||||
|
||||
enum sfp_form_factor {
|
||||
UCENTRAL_SFP_FORM_FACTOR_NA = 0,
|
||||
|
||||
UCENTRAL_SFP_FORM_FACTOR_SFP,
|
||||
UCENTRAL_SFP_FORM_FACTOR_SFP_PLUS,
|
||||
UCENTRAL_SFP_FORM_FACTOR_SFP_28,
|
||||
UCENTRAL_SFP_FORM_FACTOR_SFP_DD,
|
||||
UCENTRAL_SFP_FORM_FACTOR_QSFP,
|
||||
UCENTRAL_SFP_FORM_FACTOR_QSFP_PLUS,
|
||||
UCENTRAL_SFP_FORM_FACTOR_QSFP_28,
|
||||
UCENTRAL_SFP_FORM_FACTOR_QSFP_DD
|
||||
};
|
||||
|
||||
enum sfp_link_mode {
|
||||
UCENTRAL_SFP_LINK_MODE_NA = 0,
|
||||
|
||||
UCENTRAL_SFP_LINK_MODE_1000_X,
|
||||
UCENTRAL_SFP_LINK_MODE_2500_X,
|
||||
UCENTRAL_SFP_LINK_MODE_4000_SR,
|
||||
UCENTRAL_SFP_LINK_MODE_10G_SR,
|
||||
UCENTRAL_SFP_LINK_MODE_25G_SR,
|
||||
UCENTRAL_SFP_LINK_MODE_40G_SR,
|
||||
UCENTRAL_SFP_LINK_MODE_50G_SR,
|
||||
UCENTRAL_SFP_LINK_MODE_100G_SR,
|
||||
};
|
||||
|
||||
struct plat_port_transceiver_info {
|
||||
char vendor_name[64];
|
||||
char part_number[64];
|
||||
char serial_number[64];
|
||||
char revision[64];
|
||||
enum sfp_form_factor form_factor;
|
||||
enum sfp_link_mode *supported_link_modes;
|
||||
size_t num_supported_link_modes;
|
||||
float temperature;
|
||||
float tx_optical_power;
|
||||
float rx_optical_power;
|
||||
float max_module_power;
|
||||
};
|
||||
|
||||
struct plat_port_info {
|
||||
struct plat_port_counters stats;
|
||||
struct plat_port_lldp_peer_info lldp_peer_info;
|
||||
struct plat_ieee8021x_port_info ieee8021x_info;
|
||||
struct plat_port_transceiver_info transceiver_info;
|
||||
uint32_t uptime;
|
||||
uint32_t speed;
|
||||
uint8_t carrier_up;
|
||||
uint8_t duplex;
|
||||
uint8_t has_lldp_peer_info;
|
||||
uint8_t has_transceiver_info;
|
||||
char name[PORT_MAX_NAME_LEN];
|
||||
};
|
||||
|
||||
@@ -525,6 +645,17 @@ struct plat_system_info {
|
||||
double load_average[3]; /* 1, 5, 15 minutes load average */
|
||||
};
|
||||
|
||||
struct plat_iee8021x_coa_counters {
|
||||
uint64_t coa_req_received;
|
||||
uint64_t coa_ack_sent;
|
||||
uint64_t coa_nak_sent;
|
||||
uint64_t coa_ignored;
|
||||
uint64_t coa_wrong_attr;
|
||||
uint64_t coa_wrong_attr_value;
|
||||
uint64_t coa_wrong_session_context;
|
||||
uint64_t coa_administratively_prohibited_req;
|
||||
};
|
||||
|
||||
struct plat_state_info {
|
||||
struct plat_poe_state poe_state;
|
||||
struct plat_poe_port_state poe_ports_state[MAX_NUM_OF_PORTS];
|
||||
@@ -532,10 +663,13 @@ struct plat_state_info {
|
||||
|
||||
struct plat_port_info *port_info;
|
||||
int port_info_count;
|
||||
struct plat_port_vlan *vlan_info;
|
||||
size_t vlan_info_count;
|
||||
struct plat_learned_mac_addr *learned_mac_list;
|
||||
size_t learned_mac_list_size;
|
||||
|
||||
struct plat_system_info system_info;
|
||||
struct plat_iee8021x_coa_counters ieee8021x_global_coa_counters;
|
||||
};
|
||||
|
||||
struct plat_upgrade_info {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,16 @@ struct gnma_radius_host_key {
|
||||
char hostname[GNMA_RADIUS_CFG_HOSTNAME_STR_MAX_LEN];
|
||||
};
|
||||
|
||||
struct gnma_das_dac_host_key {
|
||||
char hostname[GNMA_RADIUS_CFG_HOSTNAME_STR_MAX_LEN];
|
||||
};
|
||||
|
||||
typedef enum _gnma_das_auth_type_t {
|
||||
GNMA_802_1X_DAS_AUTH_TYPE_ANY,
|
||||
GNMA_802_1X_DAS_AUTH_TYPE_ALL,
|
||||
GNMA_802_1X_DAS_AUTH_TYPE_SESSION_KEY,
|
||||
} gnma_das_auth_type_t;
|
||||
|
||||
struct gnma_metadata {
|
||||
char platform[GNMA_METADATA_STR_MAX_LEN];
|
||||
char hwsku[GNMA_METADATA_STR_MAX_LEN];
|
||||
@@ -59,6 +69,17 @@ typedef enum _gnma_port_stat_type_t {
|
||||
|
||||
} gnma_port_stat_type_t;
|
||||
|
||||
typedef enum _gnma_ieee8021x_das_dac_stat_type_t {
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_OUT_COA_ACK_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_OUT_COA_NAK_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_IGNORED_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_WRONG_ATTR_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_WRONG_ATTR_VALUE_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_WRONG_SESSION_CONTEXT_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_ADMINISTRATIVELY_PROHIBITED_REQ_PKTS,
|
||||
} gnma_ieee8021x_das_dac_stat_type_t;
|
||||
|
||||
struct gnma_alarm {
|
||||
const char *id;
|
||||
const char *resource;
|
||||
@@ -269,6 +290,29 @@ struct gnma_fdb_entry {
|
||||
char mac[18];
|
||||
};
|
||||
|
||||
typedef enum _gnma_igmp_version_t {
|
||||
GNMA_IGMP_VERSION_NA = 0,
|
||||
GNMA_IGMP_VERSION_1 = 1,
|
||||
GNMA_IGMP_VERSION_2 = 2,
|
||||
GNMA_IGMP_VERSION_3 = 3
|
||||
} gnma_igmp_version_t;
|
||||
|
||||
struct gnma_igmp_snoop_attr {
|
||||
bool enabled;
|
||||
bool querier_enabled;
|
||||
bool fast_leave_enabled;
|
||||
uint32_t query_interval;
|
||||
uint32_t last_member_query_interval;
|
||||
uint32_t max_response_time;
|
||||
gnma_igmp_version_t version;
|
||||
};
|
||||
|
||||
struct gnma_igmp_static_group_attr {
|
||||
struct in_addr address;
|
||||
size_t num_ports;
|
||||
struct gnma_port_key *egress_ports;
|
||||
};
|
||||
|
||||
int gnma_switch_create(/* TODO id */ /* TODO: attr (adr, login, psw) */);
|
||||
int gnma_port_admin_state_set(struct gnma_port_key *port_key, bool up);
|
||||
int gnma_port_speed_set(struct gnma_port_key *port_key, const char *speed);
|
||||
@@ -403,14 +447,33 @@ int gnma_stp_ports_enable(uint32_t list_size, struct gnma_port_key *ports_list);
|
||||
int gnma_stp_instance_set(uint16_t instance, uint16_t prio,
|
||||
uint32_t list_size, uint16_t *vid_list);
|
||||
|
||||
int gnma_stp_vids_enable(uint32_t list_size, uint16_t *vid_list);
|
||||
int gnma_stp_vids_enable_all(void);
|
||||
int gnma_stp_vids_set(uint32_t list_size, uint16_t *vid_list, bool enable);
|
||||
int gnma_stp_vids_set_all(bool enable);
|
||||
int gnma_stp_vid_set(uint16_t vid, struct gnma_stp_attr *attr);
|
||||
int gnma_stp_vid_bulk_get(struct gnma_stp_attr *list, ssize_t size);
|
||||
|
||||
int gnma_ieee8021x_system_auth_control_set(bool is_enabled);
|
||||
int gnma_ieee8021x_system_auth_control_get(bool *is_enabled);
|
||||
int gnma_ieee8021x_system_auth_clients_get(char *buf, size_t buf_size);
|
||||
int gnma_ieee8021x_das_bounce_port_ignore_set(bool bounce_port_ignore);
|
||||
int gnma_ieee8021x_das_bounce_port_ignore_get(bool *bounce_port_ignore);
|
||||
int gnma_ieee8021x_das_disable_port_ignore_set(bool disable_port_ignore);
|
||||
int gnma_ieee8021x_das_disable_port_ignore_get(bool *disable_port_ignore);
|
||||
int gnma_ieee8021x_das_ignore_server_key_set(bool ignore_server_key);
|
||||
int gnma_ieee8021x_das_ignore_server_key_get(bool *ignore_server_key);
|
||||
int gnma_ieee8021x_das_ignore_session_key_set(bool ignore_session_key);
|
||||
int gnma_ieee8021x_das_ignore_session_key_get(bool *ignore_session_key);
|
||||
int gnma_ieee8021x_das_auth_type_key_set(gnma_das_auth_type_t auth_type);
|
||||
int gnma_ieee8021x_das_auth_type_key_get(gnma_das_auth_type_t *auth_type);
|
||||
int gnma_ieee8021x_das_dac_hosts_list_get(size_t *list_size,
|
||||
struct gnma_das_dac_host_key *das_dac_keys_arr);
|
||||
int gnma_ieee8021x_das_dac_host_add(struct gnma_das_dac_host_key *key,
|
||||
const char *passkey);
|
||||
int gnma_ieee8021x_das_dac_host_remove(struct gnma_das_dac_host_key *key);
|
||||
int
|
||||
gnma_iee8021x_das_dac_global_stats_get(uint32_t num_of_counters,
|
||||
gnma_ieee8021x_das_dac_stat_type_t *counter_ids,
|
||||
uint64_t *counters);
|
||||
|
||||
int gnma_radius_hosts_list_get(size_t *list_size,
|
||||
struct gnma_radius_host_key *hosts_list);
|
||||
@@ -419,6 +482,12 @@ int gnma_radius_host_add(struct gnma_radius_host_key *key, const char *passkey,
|
||||
int gnma_radius_host_remove(struct gnma_radius_host_key *key);
|
||||
int gnma_mac_address_list_get(size_t *list_size, struct gnma_fdb_entry *list);
|
||||
int gnma_system_password_set(char *password);
|
||||
int gnma_igmp_snooping_set(uint16_t vid, struct gnma_igmp_snoop_attr *attr);
|
||||
int gnma_igmp_static_groups_set(uint16_t vid, size_t num_groups,
|
||||
struct gnma_igmp_static_group_attr *groups);
|
||||
|
||||
int gnma_igmp_iface_groups_get(struct gnma_port_key *iface,
|
||||
char *buf, size_t *buf_size);
|
||||
|
||||
struct gnma_change *gnma_change_create(void);
|
||||
void gnma_change_destory(struct gnma_change *);
|
||||
|
||||
@@ -44,6 +44,16 @@
|
||||
|
||||
#define RTTY_SESS_MAX (10)
|
||||
|
||||
#define ARR_FIND_VALUE_IDX(A, len, value) \
|
||||
({ \
|
||||
size_t it = 0; \
|
||||
for ((it) = 0; (it) < (len); (++it)) { \
|
||||
if ((A)[it] == (value)) \
|
||||
break; \
|
||||
} \
|
||||
(it); \
|
||||
})
|
||||
|
||||
static int plat_state_get(struct plat_state_info *state);
|
||||
static void plat_state_deinit(struct plat_state_info *state);
|
||||
static int plat_port_speed_get(uint16_t fp_p_id, uint32_t *speed);
|
||||
@@ -137,6 +147,17 @@ plat_ieee8021x_system_auth_clients_get(uint16_t port_id,
|
||||
} \
|
||||
(res);})
|
||||
|
||||
#define PLAT_DAC_HOST_EXISTS_IN_CFG(_host, head) \
|
||||
({bool res = false; \
|
||||
struct plat_ieee8021x_dac_list *_pos; \
|
||||
UCENTRAL_LIST_FOR_EACH_MEMBER((_pos), (head)) { \
|
||||
if (strcmp((_host), ((_pos)->host.hostname)) == 0) { \
|
||||
res = true; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
(res);})
|
||||
|
||||
/* For now, let's define abs max buf size as:
|
||||
* 1024 (bytes) per client, 10 clients total at max for 100 ports;
|
||||
* Bare minimum client info has ~600B size (raw json).
|
||||
@@ -195,15 +216,6 @@ struct poe_port {
|
||||
gnma_poe_port_priority_t priority;
|
||||
};
|
||||
|
||||
/* Password is obfuscated and key changes all the time.
|
||||
* So cache only actual hosts (ip / hostname), and do a single
|
||||
* GNMI request to add host (with all parameters - passkey, port etc) upon
|
||||
* every cfg reqest.
|
||||
*/
|
||||
struct radius_host {
|
||||
struct gnma_radius_host_key key;
|
||||
};
|
||||
|
||||
struct port {
|
||||
struct gnma_port_key key;
|
||||
struct {
|
||||
@@ -244,6 +256,13 @@ struct plat_state {
|
||||
} poe;
|
||||
struct {
|
||||
bool is_auth_control_enabled;
|
||||
bool bounce_port_ignore;
|
||||
bool disable_port_ignore;
|
||||
bool ignore_server_key;
|
||||
bool ignore_session_key;
|
||||
gnma_das_auth_type_t das_auth_type;
|
||||
struct gnma_das_dac_host_key *das_dac_keys_arr;
|
||||
size_t das_dac_keys_arr_size;
|
||||
} ieee8021x;
|
||||
struct {
|
||||
struct gnma_radius_host_key *hosts_keys_arr;
|
||||
@@ -875,6 +894,98 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int plat_state_ieee8021x_dac_list_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
free(plat_state.ieee8021x.das_dac_keys_arr);
|
||||
plat_state.ieee8021x.das_dac_keys_arr = NULL;
|
||||
plat_state.ieee8021x.das_dac_keys_arr_size = 0;
|
||||
|
||||
ret = gnma_ieee8021x_das_dac_hosts_list_get(&plat_state.ieee8021x.das_dac_keys_arr_size,
|
||||
NULL);
|
||||
if (ret && ret != GNMA_ERR_OVERFLOW) {
|
||||
UC_LOG_CRIT("gnma_ieee8021x_das_dac_hosts_list_get failed");
|
||||
plat_state.ieee8021x.das_dac_keys_arr_size = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* No DAC hosts configured, no need to update cache. */
|
||||
if (0 == plat_state.ieee8021x.das_dac_keys_arr_size)
|
||||
return 0;
|
||||
|
||||
plat_state.ieee8021x.das_dac_keys_arr =
|
||||
calloc(plat_state.ieee8021x.das_dac_keys_arr_size,
|
||||
sizeof(*plat_state.ieee8021x.das_dac_keys_arr));
|
||||
if (!plat_state.ieee8021x.das_dac_keys_arr) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = gnma_ieee8021x_das_dac_hosts_list_get(&plat_state.ieee8021x.das_dac_keys_arr_size,
|
||||
plat_state.ieee8021x.das_dac_keys_arr);
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("gnma_ieee8021x_das_dac_hosts_list_get failed");
|
||||
goto err;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free(plat_state.radius.hosts_keys_arr);
|
||||
plat_state.radius.hosts_keys_arr = NULL;
|
||||
plat_state.radius.hosts_keys_arr_size = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int plat_state_ieee8021x_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gnma_ieee8021x_system_auth_control_get(&plat_state.ieee8021x.is_auth_control_enabled);
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("gnma_ieee8021x_system_auth_control_get failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gnma_ieee8021x_das_bounce_port_ignore_get(&plat_state.ieee8021x.bounce_port_ignore);
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("gnma_ieee8021x_das_bounce_port_ignore_get failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gnma_ieee8021x_das_disable_port_ignore_get(&plat_state.ieee8021x.disable_port_ignore);
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("gnma_ieee8021x_das_disable_port_ignore_get failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gnma_ieee8021x_das_ignore_server_key_get(&plat_state.ieee8021x.ignore_server_key);
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("gnma_ieee8021x_das_ignore_server_key_get failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gnma_ieee8021x_das_ignore_session_key_get(&plat_state.ieee8021x.ignore_session_key);
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("gnma_ieee8021x_das_ignore_session_key_get failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gnma_ieee8021x_das_auth_type_key_get(&plat_state.ieee8021x.das_auth_type);
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("gnma_ieee8021x_das_auth_type_key_get failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = plat_state_ieee8021x_dac_list_init();
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("plat_state_ieee8021x_dac_list_init failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int plat_state_init()
|
||||
{
|
||||
BITMAP_DECLARE(vlans, GNMA_MAX_VLANS);
|
||||
@@ -892,9 +1003,15 @@ static int plat_state_init()
|
||||
|
||||
featsts[FEAT_CORE] = FEATSTS_FAIL;
|
||||
|
||||
ret = gnma_ieee8021x_system_auth_control_get(&plat_state.ieee8021x.is_auth_control_enabled);
|
||||
ret = plat_state_ieee8021x_init();
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("gnma_ieee8021x_system_auth_control_get failed");
|
||||
UC_LOG_CRIT("plat_state_ieee8021x_init failed");
|
||||
featsts[FEAT_AAA] = FEATSTS_FAIL;
|
||||
}
|
||||
|
||||
ret = plat_state_radius_init();
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("plat_state_radius_init failed");
|
||||
featsts[FEAT_AAA] = FEATSTS_FAIL;
|
||||
}
|
||||
|
||||
@@ -1012,12 +1129,6 @@ static int plat_state_init()
|
||||
}
|
||||
}
|
||||
|
||||
ret = plat_state_radius_init();
|
||||
if (ret) {
|
||||
UC_LOG_CRIT("plat_state_radius_init failed");
|
||||
featsts[FEAT_AAA] = FEATSTS_FAIL;
|
||||
}
|
||||
|
||||
if (featsts[FEAT_AAA] == FEATSTS_FAIL) {
|
||||
UC_LOG_CRIT("AAA feature failed to initialize");
|
||||
} else {
|
||||
@@ -1458,16 +1569,6 @@ int plat_port_stats_get(uint16_t fp_p_id, struct plat_port_counters *stats)
|
||||
uint64_t counters[ARRAY_LENGTH(stat_types)];
|
||||
struct gnma_port_key gnma_port;
|
||||
|
||||
#define ARR_FIND_VALUE_IDX(A, len, value) \
|
||||
({ \
|
||||
size_t it = 0; \
|
||||
for ((it) = 0; (it) < (len); (++it)) { \
|
||||
if ((A)[it] == (value)) \
|
||||
break; \
|
||||
} \
|
||||
(it); \
|
||||
})
|
||||
|
||||
PID_TO_NAME(fp_p_id, gnma_port.name);
|
||||
|
||||
if (gnma_port_stats_get(&gnma_port, ARRAY_LENGTH(stat_types),
|
||||
@@ -1522,7 +1623,6 @@ int plat_port_stats_get(uint16_t fp_p_id, struct plat_port_counters *stats)
|
||||
stats->tx_packets +=
|
||||
counters[ARR_FIND_VALUE_IDX(stat_types, ARRAY_LENGTH(stat_types),
|
||||
GNMA_PORT_STAT_OUT_BCAST_PKTS)];
|
||||
#undef ARR_FIND_VALUE_IDX
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1794,6 +1894,123 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int plat_port_transceiver_info_get(uint16_t port_id,
|
||||
struct plat_port_transceiver_info *info)
|
||||
{
|
||||
/* TODO */
|
||||
(void)((port_id));
|
||||
(void)((info));
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int plat_vlan_igmp_info_get(uint16_t vid, struct plat_igmp *info)
|
||||
{
|
||||
size_t list_size = 0, group_idx = 0;
|
||||
struct plat_ports_list *port_node;
|
||||
struct gnma_port_key iface = {0};
|
||||
cJSON *groups = NULL, *group;
|
||||
size_t buf_size = 0;
|
||||
char *buf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
VLAN_TO_NAME(vid, iface.name);
|
||||
ret = gnma_igmp_iface_groups_get(&iface, NULL, &buf_size);
|
||||
if (ret == GNMA_OK && !buf_size)
|
||||
return 0;
|
||||
if (ret != GNMA_ERR_OVERFLOW)
|
||||
return -1;
|
||||
|
||||
buf = calloc(buf_size, sizeof(*buf));
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
ret = gnma_igmp_iface_groups_get(&iface, buf, &buf_size);
|
||||
if (ret != GNMA_OK) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
groups = cJSON_Parse(buf);
|
||||
if (!groups) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
list_size = cJSON_GetArraySize(groups);
|
||||
info->groups = calloc(list_size, sizeof(*info->groups));
|
||||
if (!info->groups) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
info->num_groups = list_size;
|
||||
|
||||
cJSON_ArrayForEach(group, groups) {
|
||||
cJSON *state, *gaddr, *e_ifaces, *e_iface;
|
||||
|
||||
state = cJSON_GetObjectItemCaseSensitive(group, "state");
|
||||
if (!state || !cJSON_IsObject(state)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
gaddr = cJSON_GetObjectItemCaseSensitive(state, "group");
|
||||
if (!gaddr || !cJSON_GetStringValue(gaddr)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
e_ifaces = cJSON_GetObjectItemCaseSensitive(state, "outgoing-interface");
|
||||
if (!e_ifaces || !cJSON_IsArray(e_ifaces)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, cJSON_GetStringValue(gaddr),
|
||||
&info->groups[group_idx].addr) != 1) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
cJSON_ArrayForEach(e_iface, e_ifaces) {
|
||||
if (!cJSON_GetStringValue(e_iface)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
port_node = calloc(1, sizeof(*port_node));
|
||||
if (!port_node) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
strncpy(port_node->name,
|
||||
cJSON_GetStringValue(e_iface),
|
||||
sizeof(port_node->name));
|
||||
UCENTRAL_LIST_PUSH_MEMBER(
|
||||
&info->groups[group_idx].egress_ports_list,
|
||||
port_node);
|
||||
}
|
||||
group_idx++;
|
||||
}
|
||||
|
||||
info->exist = true;
|
||||
goto exit;
|
||||
|
||||
err:
|
||||
if (info->groups) {
|
||||
for (size_t i = 0; i < info->num_groups; ++i) {
|
||||
UCENTRAL_LIST_DESTROY_SAFE(
|
||||
&info->groups[i].egress_ports_list,
|
||||
port_node);
|
||||
}
|
||||
}
|
||||
free(info->groups);
|
||||
exit:
|
||||
cJSON_Delete(groups);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
__poe_port_state_buf_parse(char *buf, size_t buf_size,
|
||||
struct plat_poe_port_state *port_state)
|
||||
@@ -1920,6 +2137,7 @@ __poe_state_buf_parse(char *buf, size_t buf_size,
|
||||
{
|
||||
cJSON *status;
|
||||
cJSON *state;
|
||||
cJSON *tmp;
|
||||
|
||||
state = cJSON_ParseWithLength(buf, buf_size);
|
||||
if (!state)
|
||||
@@ -1927,10 +2145,19 @@ __poe_state_buf_parse(char *buf, size_t buf_size,
|
||||
|
||||
poe_state->max_power_budget =
|
||||
cJSON_GetNumberValue(cJSON_GetObjectItemCaseSensitive(state, "max-power-budget"));
|
||||
|
||||
/* For some reason, new BRCM images report this value as string, not value... */
|
||||
tmp = cJSON_GetObjectItemCaseSensitive(state, "power-threshold");
|
||||
if (!tmp || !cJSON_GetStringValue(tmp))
|
||||
goto err;
|
||||
poe_state->power_threshold =
|
||||
cJSON_GetNumberValue(cJSON_GetObjectItemCaseSensitive(state, "power-threshold"));
|
||||
(typeof(poe_state->power_threshold)) strtod(cJSON_GetStringValue(tmp), NULL);
|
||||
|
||||
tmp = cJSON_GetObjectItemCaseSensitive(state, "power-consumption");
|
||||
if (!tmp || !cJSON_GetStringValue(tmp))
|
||||
goto err;
|
||||
poe_state->power_consumed =
|
||||
cJSON_GetNumberValue(cJSON_GetObjectItemCaseSensitive(state, "power-consumption"));
|
||||
(typeof(poe_state->power_consumed)) strtod(cJSON_GetStringValue(tmp), NULL);
|
||||
|
||||
status = cJSON_GetObjectItemCaseSensitive(state, "pse-oper-status");
|
||||
if (!cJSON_GetStringValue(status))
|
||||
@@ -2792,6 +3019,11 @@ err:
|
||||
/* NOTE: In case of error this function left partial config */
|
||||
int plat_vlan_rif_set(uint16_t vid, struct plat_ipv4 *ipv4)
|
||||
{
|
||||
struct gnma_igmp_snoop_attr igmp_snoop_attr = {
|
||||
.enabled=false,
|
||||
.querier_enabled=false,
|
||||
.version=GNMA_IGMP_VERSION_NA
|
||||
};
|
||||
struct gnma_ip_prefix pref, pref_old;
|
||||
uint16_t list_size;
|
||||
int i;
|
||||
@@ -2818,6 +3050,11 @@ int plat_vlan_rif_set(uint16_t vid, struct plat_ipv4 *ipv4)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gnma_igmp_snooping_set(vid, &igmp_snoop_attr)) {
|
||||
UC_LOG_DBG("Failed to set VLAN igmp.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (list_size > 0 && !ipv4->exist) {
|
||||
/* Force DHCP cache/state flush (delete), as at this point no
|
||||
* dhcp cfg for this vlan exists, and it won't be 'restored'
|
||||
@@ -2852,6 +3089,83 @@ int plat_vlan_rif_set(uint16_t vid, struct plat_ipv4 *ipv4)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int plat_vlan_igmp_set(uint16_t vid, struct plat_igmp *igmp)
|
||||
{
|
||||
struct gnma_igmp_static_group_attr *group_list;
|
||||
struct plat_ports_list *e_port;
|
||||
size_t group_idx, port_idx;
|
||||
int ret;
|
||||
struct gnma_igmp_snoop_attr attr = {
|
||||
.last_member_query_interval = igmp->last_member_query_interval,
|
||||
.fast_leave_enabled = igmp->fast_leave_enabled,
|
||||
.max_response_time = igmp->max_response_time,
|
||||
.querier_enabled = igmp->querier_enabled,
|
||||
.query_interval = igmp->query_interval,
|
||||
.enabled = igmp->snooping_enabled,
|
||||
};
|
||||
|
||||
if (!igmp->exist)
|
||||
attr.version = GNMA_IGMP_VERSION_NA;
|
||||
else if (igmp->version == PLAT_IGMP_VERSION_1)
|
||||
attr.version = GNMA_IGMP_VERSION_1;
|
||||
else if (igmp->version == PLAT_IGMP_VERSION_2)
|
||||
attr.version = GNMA_IGMP_VERSION_2;
|
||||
else if (igmp->version == PLAT_IGMP_VERSION_3)
|
||||
attr.version = GNMA_IGMP_VERSION_3;
|
||||
else
|
||||
return -1;
|
||||
|
||||
group_list = calloc(igmp->num_groups, sizeof(*group_list));
|
||||
if (!group_list) {
|
||||
UC_LOG_ERR("ENOMEM");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (group_idx = 0; group_idx < igmp->num_groups; group_idx++) {
|
||||
group_list[group_idx].address = igmp->groups[group_idx].addr;
|
||||
|
||||
group_list[group_idx].num_ports = 0;
|
||||
UCENTRAL_LIST_FOR_EACH_MEMBER(e_port, &igmp->groups[group_idx].egress_ports_list) {
|
||||
group_list[group_idx].num_ports++;
|
||||
}
|
||||
group_list[group_idx].egress_ports = calloc(group_list[group_idx].num_ports,
|
||||
sizeof(*group_list[group_idx].egress_ports));
|
||||
if (!group_list[group_idx].egress_ports) {
|
||||
UC_LOG_ERR("ENOMEM");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
port_idx = 0;
|
||||
UCENTRAL_LIST_FOR_EACH_MEMBER(e_port, &igmp->groups[group_idx].egress_ports_list) {
|
||||
strncpy(group_list[group_idx].egress_ports[port_idx].name,
|
||||
e_port->name,
|
||||
sizeof(group_list[group_idx].egress_ports[port_idx].name));
|
||||
port_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
ret = gnma_igmp_snooping_set(vid, &attr);
|
||||
if (ret) {
|
||||
UC_LOG_ERR("gnma_igmp_snooping_set");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = gnma_igmp_static_groups_set(vid, igmp->num_groups, group_list);
|
||||
if (ret) {
|
||||
UC_LOG_ERR("gnma_igmp_static_groups_set");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
err:
|
||||
if (group_list)
|
||||
for (group_idx = 0; group_idx < igmp->num_groups; group_idx++)
|
||||
free(group_list[group_idx].egress_ports);
|
||||
free(group_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* NOTE: In case of error this function left partial config */
|
||||
int plat_portl2_rif_set(uint16_t fp_p_id, struct plat_ipv4 *ipv4)
|
||||
{
|
||||
@@ -2887,8 +3201,31 @@ int plat_portl2_rif_set(uint16_t fp_p_id, struct plat_ipv4 *ipv4)
|
||||
|
||||
static void plat_state_deinit(struct plat_state_info *state)
|
||||
{
|
||||
struct plat_ports_list *port_node;
|
||||
|
||||
for (int i = 0; i < state->port_info_count; i++) {
|
||||
if (state->port_info[i].has_transceiver_info &&
|
||||
state->port_info[i].transceiver_info.num_supported_link_modes) {
|
||||
free(state->port_info[i].transceiver_info.supported_link_modes);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < state->vlan_info_count; i++) {
|
||||
struct plat_igmp *info = &state->vlan_info[i].igmp;
|
||||
|
||||
if (info->num_groups) {
|
||||
for (size_t i = 0; i < info->num_groups; ++i) {
|
||||
UCENTRAL_LIST_DESTROY_SAFE(
|
||||
&info->groups[i].egress_ports_list,
|
||||
port_node);
|
||||
}
|
||||
free(info->groups);
|
||||
}
|
||||
}
|
||||
|
||||
free(state->learned_mac_list);
|
||||
free(state->port_info);
|
||||
free(state->vlan_info);
|
||||
*state = (struct plat_state_info){ 0 };
|
||||
}
|
||||
|
||||
@@ -2954,6 +3291,11 @@ static int plat_port_info_get(struct plat_port_info **port_info, int *count)
|
||||
pinfo[i].has_lldp_peer_info = 1;
|
||||
}
|
||||
|
||||
if (!plat_port_transceiver_info_get(pid,
|
||||
&pinfo[i].transceiver_info)) {
|
||||
pinfo[i].has_transceiver_info = 1;
|
||||
}
|
||||
|
||||
plat_ieee8021x_system_auth_clients_get(pid,
|
||||
&ieee8021x_buf,
|
||||
&ieee8021x_buf_size,
|
||||
@@ -2973,6 +3315,54 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int plat_vlan_info_get(struct plat_port_vlan **vlan_info, size_t *count)
|
||||
{
|
||||
BITMAP_DECLARE(vlans_bmp, GNMA_MAX_VLANS);
|
||||
struct plat_port_vlan *vinfo = 0;
|
||||
size_t num_vlans = 0;
|
||||
size_t idx = 0;
|
||||
size_t vid;
|
||||
int ret;
|
||||
|
||||
BITMAP_CLEAR(vlans_bmp, GNMA_MAX_VLANS);
|
||||
ret = gnma_vlan_list_get(vlans_bmp);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
BITMAP_FOR_EACH_BIT_SET(vid, vlans_bmp, GNMA_MAX_VLANS) {
|
||||
num_vlans++;
|
||||
}
|
||||
|
||||
if (!num_vlans) {
|
||||
*count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
vinfo = calloc(num_vlans, sizeof(*vinfo));
|
||||
if (!vinfo) {
|
||||
UC_LOG_ERR("ENOMEM");
|
||||
return -1;
|
||||
}
|
||||
memset(vinfo, 0, num_vlans * sizeof(*vinfo));
|
||||
|
||||
BITMAP_FOR_EACH_BIT_SET(vid, vlans_bmp, GNMA_MAX_VLANS) {
|
||||
vinfo[idx].id = vid;
|
||||
|
||||
if (plat_vlan_igmp_info_get(vid, &vinfo[idx].igmp)) {
|
||||
UC_LOG_DBG("plat_vlan_igmp_info_get failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
idx++;
|
||||
if (idx >= num_vlans)
|
||||
break;
|
||||
}
|
||||
|
||||
*count = idx;
|
||||
*vlan_info = vinfo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_meminfo_cached_kib(uint64_t *cached)
|
||||
{
|
||||
size_t n;
|
||||
@@ -3074,6 +3464,54 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
plat_state_ieee8021x_coa_global_counters_get(struct plat_iee8021x_coa_counters *stats)
|
||||
{
|
||||
gnma_ieee8021x_das_dac_stat_type_t stat_types[] = {
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_OUT_COA_ACK_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_OUT_COA_NAK_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_IGNORED_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_WRONG_ATTR_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_WRONG_ATTR_VALUE_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_WRONG_SESSION_CONTEXT_PKTS,
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_ADMINISTRATIVELY_PROHIBITED_REQ_PKTS,
|
||||
};
|
||||
uint64_t counters[ARRAY_LENGTH(stat_types)];
|
||||
|
||||
if (gnma_iee8021x_das_dac_global_stats_get(ARRAY_LENGTH(stat_types),
|
||||
&stat_types[0],
|
||||
&counters[0]))
|
||||
return -EINVAL;
|
||||
|
||||
stats->coa_req_received =
|
||||
counters[ARR_FIND_VALUE_IDX(stat_types, ARRAY_LENGTH(stat_types),
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_PKTS)];
|
||||
stats->coa_ack_sent =
|
||||
counters[ARR_FIND_VALUE_IDX(stat_types, ARRAY_LENGTH(stat_types),
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_OUT_COA_ACK_PKTS)];
|
||||
stats->coa_nak_sent =
|
||||
counters[ARR_FIND_VALUE_IDX(stat_types, ARRAY_LENGTH(stat_types),
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_OUT_COA_NAK_PKTS)];
|
||||
stats->coa_ignored =
|
||||
counters[ARR_FIND_VALUE_IDX(stat_types, ARRAY_LENGTH(stat_types),
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_IGNORED_PKTS)];
|
||||
stats->coa_wrong_attr =
|
||||
counters[ARR_FIND_VALUE_IDX(stat_types, ARRAY_LENGTH(stat_types),
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_WRONG_ATTR_PKTS)];
|
||||
stats->coa_wrong_attr_value =
|
||||
counters[ARR_FIND_VALUE_IDX(stat_types, ARRAY_LENGTH(stat_types),
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_WRONG_ATTR_VALUE_PKTS)];
|
||||
stats->coa_wrong_session_context =
|
||||
counters[ARR_FIND_VALUE_IDX(stat_types, ARRAY_LENGTH(stat_types),
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_WRONG_SESSION_CONTEXT_PKTS)];
|
||||
stats->coa_administratively_prohibited_req =
|
||||
counters[ARR_FIND_VALUE_IDX(stat_types, ARRAY_LENGTH(stat_types),
|
||||
GNMA_IEEE8021X_DAS_DAC_STAT_IN_COA_ADMINISTRATIVELY_PROHIBITED_REQ_PKTS)];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int plat_state_get(struct plat_state_info *state)
|
||||
{
|
||||
size_t i;
|
||||
@@ -3092,10 +3530,16 @@ static int plat_state_get(struct plat_state_info *state)
|
||||
if (plat_port_info_get(&state->port_info, &state->port_info_count))
|
||||
return -1;
|
||||
|
||||
if (plat_vlan_info_get(&state->vlan_info, &state->vlan_info_count))
|
||||
return -1;
|
||||
|
||||
if (plat_learned_mac_addrs_get(&state->learned_mac_list,
|
||||
&state->learned_mac_list_size))
|
||||
return -1;
|
||||
|
||||
if (plat_state_ieee8021x_coa_global_counters_get(&state->ieee8021x_global_coa_counters))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3111,6 +3555,12 @@ static int config_vlan_ipv4_apply(struct plat_cfg *cfg)
|
||||
UC_LOG_DBG("Failed to set VLAN rif.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = plat_vlan_igmp_set(cfg->vlans[i].id, &cfg->vlans[i].igmp);
|
||||
if (ret) {
|
||||
UC_LOG_DBG("Failed to set VLAN igmp.\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3896,20 +4346,90 @@ static int plat_port_config_apply(struct plat_cfg *cfg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int plat_dac_list_set(struct plat_ieee8021x_dac_list *hosts)
|
||||
{
|
||||
struct plat_ieee8021x_dac_list *iter;
|
||||
bool cache_changed = false;
|
||||
int ret = 0;
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
* Check cache and remove any host that is not present in
|
||||
* requested CFG (same as for VLAN: if not present in cfg = to
|
||||
* be removed).
|
||||
*/
|
||||
for (i = 0; i < plat_state.ieee8021x.das_dac_keys_arr_size; ++i) {
|
||||
if (!PLAT_DAC_HOST_EXISTS_IN_CFG(plat_state.ieee8021x.das_dac_keys_arr[i].hostname, &hosts)) {
|
||||
UC_LOG_DBG("Removing DAC server <%s> (not in cfg, present on system)\n",
|
||||
plat_state.ieee8021x.das_dac_keys_arr[i].hostname);
|
||||
ret = gnma_ieee8021x_das_dac_host_remove(&plat_state.ieee8021x.das_dac_keys_arr[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
cache_changed = true;
|
||||
} else {
|
||||
/* Special case, when host exists in cache and new CFG omitted password:
|
||||
* - remove previous entry
|
||||
* - recreate it without specifying password.
|
||||
* Either way SONIC treats this host as if password is set
|
||||
* explicitly, and might result in false-obfuscations of
|
||||
* DaS / CoA exchange between DAC and switch.
|
||||
*/
|
||||
UCENTRAL_LIST_FOR_EACH_MEMBER(iter, &hosts) {
|
||||
if (!strcmp(plat_state.ieee8021x.das_dac_keys_arr[i].hostname,
|
||||
iter->host.hostname) &&
|
||||
iter->host.passkey[0] == '\0') {
|
||||
ret = gnma_ieee8021x_das_dac_host_remove(&plat_state.ieee8021x.das_dac_keys_arr[i]);
|
||||
if (ret) {
|
||||
UC_LOG_DBG("Failed to remove DAC host <%s> (new CFG pass is empty, tried to delete))\n",
|
||||
plat_state.ieee8021x.das_dac_keys_arr[i].hostname);
|
||||
return ret;
|
||||
}
|
||||
cache_changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add any new hosts that are present in requested CFG. */
|
||||
UCENTRAL_LIST_FOR_EACH_MEMBER(iter, &hosts) {
|
||||
struct gnma_das_dac_host_key key;
|
||||
|
||||
strcpy(key.hostname, iter->host.hostname);
|
||||
|
||||
ret = gnma_ieee8021x_das_dac_host_add(&key, iter->host.passkey);
|
||||
if (ret)
|
||||
return ret;
|
||||
cache_changed = true;
|
||||
}
|
||||
|
||||
/* Reinit DAC hosts cache. */
|
||||
if (cache_changed)
|
||||
plat_state_ieee8021x_dac_list_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_ieee8021x_apply(struct plat_cfg *cfg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (cfg->ieee8021x_is_auth_ctrl_enabled != plat_state.ieee8021x.is_auth_control_enabled) {
|
||||
if (cfg->ieee8021x.is_auth_ctrl_enabled != plat_state.ieee8021x.is_auth_control_enabled) {
|
||||
UC_LOG_DBG("802.1x: changing global auth ctrl state from %d to %d",
|
||||
plat_state.ieee8021x.is_auth_control_enabled,
|
||||
cfg->ieee8021x_is_auth_ctrl_enabled);
|
||||
ret = gnma_ieee8021x_system_auth_control_set(cfg->ieee8021x_is_auth_ctrl_enabled);
|
||||
cfg->ieee8021x.is_auth_ctrl_enabled);
|
||||
ret = gnma_ieee8021x_system_auth_control_set(cfg->ieee8021x.is_auth_ctrl_enabled);
|
||||
if (ret) {
|
||||
UC_LOG_DBG("802.1x: Failed to set global auth ctrl state.");
|
||||
return ret;
|
||||
}
|
||||
plat_state.ieee8021x.is_auth_control_enabled = cfg->ieee8021x_is_auth_ctrl_enabled;
|
||||
plat_state.ieee8021x.is_auth_control_enabled = cfg->ieee8021x.is_auth_ctrl_enabled;
|
||||
}
|
||||
|
||||
ret = plat_dac_list_set(cfg->ieee8021x.das_dac_list);
|
||||
if (ret) {
|
||||
UC_LOG_DBG("802.1x: DAS: Failed to configure DAC hosts list.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = plat_radius_hosts_list_set(cfg->radius_hosts_list);
|
||||
@@ -4003,6 +4523,7 @@ void plat_config_destroy(struct plat_cfg *cfg)
|
||||
{
|
||||
struct plat_vlan_memberlist *member_node = NULL;
|
||||
struct plat_radius_hosts_list *hosts_node = NULL;
|
||||
struct plat_ports_list *port_node;
|
||||
size_t i;
|
||||
|
||||
if (!cfg)
|
||||
@@ -4019,6 +4540,14 @@ void plat_config_destroy(struct plat_cfg *cfg)
|
||||
cfg->vlans[i].members_list_head = NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 0; ++i) {
|
||||
UCENTRAL_LIST_DESTROY_SAFE(&cfg->port_isolation_cfg.sessions[i].uplink.ports_list,
|
||||
port_node);
|
||||
UCENTRAL_LIST_DESTROY_SAFE(&cfg->port_isolation_cfg.sessions[i].uplink.ports_list,
|
||||
port_node);
|
||||
}
|
||||
free(cfg->port_isolation_cfg.sessions);
|
||||
|
||||
UCENTRAL_LIST_DESTROY_SAFE(&cfg->radius_hosts_list,
|
||||
hosts_node);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#define STR(x) #x
|
||||
|
||||
#define PLATFORM_REL_NUM 1.6
|
||||
#define PLATFORM_BUILD_NUM 4
|
||||
#define PLATFORM_BUILD_NUM 5
|
||||
|
||||
#ifndef PLATFORM_REVISION
|
||||
#define PLATFORM_REVISION "Rel " XSTR(PLATFORM_REL_NUM) " build " XSTR(PLATFORM_BUILD_NUM)
|
||||
|
||||
@@ -906,6 +906,171 @@ cfg_ethernet_ieee8021x_parse(cJSON *ieee8021x, struct plat_port *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cfg_ethernet_port_isolation_interface_parse(cJSON *iface,
|
||||
struct plat_port_isolation_session_ports *ports) {
|
||||
struct plat_ports_list *port_node = NULL;
|
||||
cJSON *iface_list;
|
||||
int i;
|
||||
|
||||
iface_list = cJSON_GetObjectItemCaseSensitive(iface, "interface-list");
|
||||
if (!iface_list || !cJSON_IsArray(iface_list) ||
|
||||
cJSON_GetArraySize(iface_list) == 0) {
|
||||
UC_LOG_ERR("Ethernet obj 'port_isolation:interface-list' is invalid, parse failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < cJSON_GetArraySize(iface_list); ++i) {
|
||||
if (!cJSON_GetStringValue(cJSON_GetArrayItem(iface_list, i))) {
|
||||
UC_LOG_ERR("Ethernet obj 'port_isolation:interface-list:%d' has invalid port name, parse failed\n",
|
||||
i);
|
||||
return -1;
|
||||
}
|
||||
port_node = calloc(1, sizeof(*port_node));
|
||||
if (!port_node) {
|
||||
UC_LOG_ERR("Failed alloc port list list\n");
|
||||
return -1;
|
||||
}
|
||||
strcpy(port_node->name,
|
||||
cJSON_GetStringValue(cJSON_GetArrayItem(iface_list, i)));
|
||||
UCENTRAL_LIST_PUSH_MEMBER(&ports->ports_list, port_node);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cfg_ethernet_port_isolation_parse(cJSON *ethernet, struct plat_cfg *cfg) {
|
||||
cJSON *eth = NULL, *port_isolation, *sessions, *session;
|
||||
struct plat_port_isolation_session *session_arr;
|
||||
struct plat_ports_list *port_node = NULL;
|
||||
int i = 0, j = 0;
|
||||
|
||||
cJSON_ArrayForEach(eth, ethernet) {
|
||||
port_isolation = cJSON_GetObjectItemCaseSensitive(eth, "port-isolation");
|
||||
if (!port_isolation)
|
||||
continue;
|
||||
|
||||
if (!cJSON_IsObject(port_isolation)) {
|
||||
UC_LOG_ERR("Ethernet obj holds 'port_isolation' object of wrongful type, parse failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sessions = cJSON_GetObjectItemCaseSensitive(port_isolation,
|
||||
"sessions");
|
||||
if (!sessions || !cJSON_IsArray(sessions)) {
|
||||
UC_LOG_ERR("Ethernet obj holds 'port_isolation:sessions' array of wrongful type (or empty), parse failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON_ArrayForEach(session, sessions) {
|
||||
cfg->port_isolation_cfg.sessions_num++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->port_isolation_cfg.sessions_num == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
session_arr = calloc(cfg->port_isolation_cfg.sessions_num,
|
||||
sizeof(struct plat_port_isolation_session));
|
||||
cfg->port_isolation_cfg.sessions = session_arr;
|
||||
|
||||
if (!session_arr) {
|
||||
UC_LOG_ERR("Failed to alloc memory for port-isolation-cfg, parse failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON_ArrayForEach(eth, ethernet) {
|
||||
port_isolation = cJSON_GetObjectItemCaseSensitive(eth, "port-isolation");
|
||||
if (!port_isolation)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Highly unlikeable that the object is missing / invalid,
|
||||
* as it was okay prior (parsing above).
|
||||
* But this is still a sanity-check, in case if JSON
|
||||
* got corrupted for some reason.
|
||||
*/
|
||||
if (!cJSON_IsObject(port_isolation)) {
|
||||
UC_LOG_ERR("Ethernet obj holds 'port_isolation' object of wrongful type, parse failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sessions = cJSON_GetObjectItemCaseSensitive(port_isolation,
|
||||
"sessions");
|
||||
if (!sessions || !cJSON_IsArray(sessions)) {
|
||||
UC_LOG_ERR("Ethernet obj holds 'port_isolation:sessions' array of wrongful type (or empty), parse failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON_ArrayForEach(session, sessions) {
|
||||
cJSON *id, *uplink, *downlink;
|
||||
double session_arrid;
|
||||
|
||||
id = cJSON_GetObjectItemCaseSensitive(session, "id");
|
||||
if (!id || !cJSON_IsNumber(id)) {
|
||||
UC_LOG_ERR("Ethernet obj 'port_isolation:id' is invalid, parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
session_arrid = cJSON_GetNumberValue(id);
|
||||
|
||||
if (i > 0) {
|
||||
for (int j = i - 1; j >= 0; --j) {
|
||||
if ((double) session_arr[j].id == session_arrid) {
|
||||
UC_LOG_ERR("Expected unique 'port_isolation:id', duplicate (%lu) detected, parse failed\n",
|
||||
(uint64_t) session_arrid);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
session_arr[j].id = (uint64_t) session_arrid;
|
||||
|
||||
uplink = cJSON_GetObjectItemCaseSensitive(session,
|
||||
"uplink");
|
||||
if (!uplink || !cJSON_IsObject(uplink)) {
|
||||
UC_LOG_ERR("Ethernet obj 'port_isolation:uplink' is invalid, parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
downlink = cJSON_GetObjectItemCaseSensitive(session,
|
||||
"downlink");
|
||||
if (!downlink || !cJSON_IsObject(downlink)) {
|
||||
UC_LOG_ERR("Ethernet obj 'port_isolation:downlink' is invalid, parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (cfg_ethernet_port_isolation_interface_parse(uplink,
|
||||
&session_arr[j].uplink)) {
|
||||
UC_LOG_ERR("Ethernet obj 'port_isolation:uplink' parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (cfg_ethernet_port_isolation_interface_parse(downlink,
|
||||
&session_arr[j].downlink)) {
|
||||
UC_LOG_ERR("Ethernet obj 'port_isolation:downlink' parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
for (int j = i; j >= 0; --j) {
|
||||
UCENTRAL_LIST_DESTROY_SAFE(&session_arr[j].uplink.ports_list,
|
||||
port_node);
|
||||
UCENTRAL_LIST_DESTROY_SAFE(&session_arr[j].downlink.ports_list,
|
||||
port_node);
|
||||
}
|
||||
cfg->port_isolation_cfg.sessions = 0;
|
||||
free(cfg->port_isolation_cfg.sessions);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cfg_ethernet_parse(cJSON *ethernet, struct plat_cfg *cfg)
|
||||
{
|
||||
cJSON *eth = NULL;
|
||||
@@ -986,6 +1151,11 @@ static int cfg_ethernet_parse(cJSON *ethernet, struct plat_cfg *cfg)
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_ethernet_port_isolation_parse(ethernet, cfg)) {
|
||||
UC_LOG_ERR("port-isolation config parse faile\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1063,6 +1233,121 @@ static int cfg_port_interface_parse(cJSON *interface, struct plat_cfg *cfg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cfg_vlan_interface_parse_multicast(cJSON *multicast,
|
||||
struct plat_cfg *cfg,
|
||||
uint16_t vid)
|
||||
{
|
||||
cJSON *igmp, *field, *group, *addr, *ports, *port;
|
||||
struct plat_ports_list *e_port;
|
||||
struct plat_igmp info = { /* default values */
|
||||
.snooping_enabled = true,
|
||||
.querier_enabled = false,
|
||||
.fast_leave_enabled = false,
|
||||
.query_interval = 60,
|
||||
.last_member_query_interval = 60,
|
||||
.max_response_time = 10,
|
||||
.version = PLAT_IGMP_VERSION_3,
|
||||
.num_groups = 0,
|
||||
.groups = NULL
|
||||
};
|
||||
size_t group_idx;
|
||||
|
||||
if (!(igmp = cJSON_GetObjectItemCaseSensitive(multicast, "igmp")))
|
||||
return 0;
|
||||
|
||||
/* handle igmp snooping parameters */
|
||||
if ((field = cJSON_GetObjectItemCaseSensitive(igmp, "version")) && cJSON_IsNumber(field)) {
|
||||
switch ((uint32_t)cJSON_GetNumberValue(field)) {
|
||||
case 1:
|
||||
info.version = PLAT_IGMP_VERSION_1;
|
||||
break;
|
||||
case 2:
|
||||
info.version = PLAT_IGMP_VERSION_2;
|
||||
break;
|
||||
case 3:
|
||||
info.version = PLAT_IGMP_VERSION_3;
|
||||
break;
|
||||
default:
|
||||
UC_LOG_ERR("Invalid IGMP version %f", cJSON_GetNumberValue(field));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if ((field = cJSON_GetObjectItemCaseSensitive(igmp, "snooping-enable")) && cJSON_IsBool(field))
|
||||
info.snooping_enabled = cJSON_IsTrue(field);
|
||||
if ((field = cJSON_GetObjectItemCaseSensitive(igmp, "querier-enable")) && cJSON_IsBool(field))
|
||||
info.querier_enabled = cJSON_IsTrue(field);
|
||||
if ((field = cJSON_GetObjectItemCaseSensitive(igmp, "fast-leave-enable")) && cJSON_IsBool(field))
|
||||
info.fast_leave_enabled = cJSON_IsTrue(field);
|
||||
if ((field = cJSON_GetObjectItemCaseSensitive(igmp, "query-interval")) && cJSON_IsNumber(field))
|
||||
info.query_interval = cJSON_GetNumberValue(field);
|
||||
if ((field = cJSON_GetObjectItemCaseSensitive(igmp, "last-member-query-interval")) && cJSON_IsNumber(field))
|
||||
info.last_member_query_interval = cJSON_GetNumberValue(field);
|
||||
if ((field = cJSON_GetObjectItemCaseSensitive(igmp, "max-response-time")) && cJSON_IsNumber(field))
|
||||
info.max_response_time = cJSON_GetNumberValue(field);
|
||||
|
||||
field = cJSON_GetObjectItemCaseSensitive(igmp, "static-mcast-groups");
|
||||
if (!field || !cJSON_IsArray(field))
|
||||
goto skip_groups;
|
||||
|
||||
info.num_groups = cJSON_GetArraySize(field);
|
||||
info.groups = calloc(info.num_groups, sizeof(*info.groups));
|
||||
if (!info.groups)
|
||||
goto err;
|
||||
|
||||
/* handle static groups */
|
||||
group_idx = 0;
|
||||
cJSON_ArrayForEach(group, field) {
|
||||
addr = cJSON_GetObjectItemCaseSensitive(group, "address");
|
||||
ports = cJSON_GetObjectItemCaseSensitive(group, "egress-ports");
|
||||
if (!addr || !cJSON_IsString(addr) || !ports || !cJSON_IsArray(ports)) {
|
||||
/* FIXME: workaround for parser issue */
|
||||
addr = cJSON_GetObjectItemCaseSensitive(group, "static-mcast-groups[].address");
|
||||
ports = cJSON_GetObjectItemCaseSensitive(group, "static-mcast-groups[].egress-ports");
|
||||
if (!addr || !cJSON_IsString(addr) || !ports || !cJSON_IsArray(ports)) {
|
||||
UC_LOG_ERR("Missing static group info\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, addr->valuestring, &info.groups[group_idx].addr.s_addr) != 1) {
|
||||
UC_LOG_ERR("Failed to parse ip addr %s\n", addr->valuestring);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* handle egress ports */
|
||||
cJSON_ArrayForEach(port, ports) {
|
||||
e_port = calloc(1, sizeof(*e_port));
|
||||
if (!e_port) {
|
||||
UC_LOG_ERR("Can't alloc port node\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!cJSON_IsString(port)){
|
||||
UC_LOG_ERR("Invalid port name\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
strncpy(e_port->name, port->valuestring, sizeof(e_port->name));
|
||||
UCENTRAL_LIST_PUSH_MEMBER(&info.groups[group_idx].egress_ports_list, e_port);
|
||||
}
|
||||
group_idx++;
|
||||
}
|
||||
skip_groups:
|
||||
info.exist = info.snooping_enabled || info.querier_enabled;
|
||||
cfg->vlans[vid].igmp = info;
|
||||
return 0;
|
||||
err:
|
||||
if (info.groups) {
|
||||
for (group_idx = 0; group_idx < info.num_groups; group_idx++) {
|
||||
UCENTRAL_LIST_DESTROY_SAFE(
|
||||
&info.groups[group_idx].egress_ports_list,
|
||||
e_port);
|
||||
}
|
||||
}
|
||||
free(info.groups);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cfg_vlan_interface_parse(cJSON *interface, struct plat_cfg *cfg)
|
||||
{
|
||||
size_t i;
|
||||
@@ -1076,6 +1361,7 @@ static int cfg_vlan_interface_parse(cJSON *interface, struct plat_cfg *cfg)
|
||||
char *ipv4_subnet_str;
|
||||
cJSON *select_ports;
|
||||
cJSON *ipv4_subnet;
|
||||
cJSON *multicast;
|
||||
cJSON *vlan_tag;
|
||||
cJSON *ethernet;
|
||||
uint8_t tagged;
|
||||
@@ -1141,6 +1427,7 @@ static int cfg_vlan_interface_parse(cJSON *interface, struct plat_cfg *cfg)
|
||||
cfg->vlans[vid].dhcp.relay.enabled = false;
|
||||
ipv4 = cJSON_GetObjectItemCaseSensitive(interface, "ipv4");
|
||||
dhcp = cJSON_GetObjectItemCaseSensitive(ipv4, "dhcp");
|
||||
multicast = cJSON_GetObjectItemCaseSensitive(ipv4, "multicast");
|
||||
if (ipv4) {
|
||||
/* TODO addressing */
|
||||
ipv4_subnet_str = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(ipv4, "subnet"));
|
||||
@@ -1181,6 +1468,13 @@ skip_subnet_old:
|
||||
}
|
||||
cfg->vlans[vid].ipv4.exist = true;
|
||||
skip_subnet:
|
||||
if (multicast) {
|
||||
ret = __cfg_vlan_interface_parse_multicast(multicast, cfg, vid);
|
||||
if (ret) {
|
||||
UC_LOG_ERR("Failed parsing multicast config");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dhcp)
|
||||
return 0;
|
||||
@@ -1333,6 +1627,59 @@ static int cfg_services_parse(cJSON *services, struct plat_cfg *cfg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set default values in case if no cfg supplied */
|
||||
cfg->enabled_services_cfg.ssh.enabled = false;
|
||||
cfg->enabled_services_cfg.telnet.enabled = false;
|
||||
cfg->enabled_services_cfg.http.enabled = false;
|
||||
|
||||
s = cJSON_GetObjectItemCaseSensitive(services, "ssh");
|
||||
if (s) {
|
||||
if (!cJSON_IsObject(s)) {
|
||||
UC_LOG_ERR("Unexpected type of services:ssh: Object expected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON *enable = cJSON_GetObjectItemCaseSensitive(s, "enable");
|
||||
if (enable && !cJSON_IsBool(enable)) {
|
||||
UC_LOG_ERR("Unexpected type of services:ssh:enable: Boolean expected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfg->enabled_services_cfg.ssh.enabled = cJSON_IsTrue(enable);
|
||||
}
|
||||
|
||||
s = cJSON_GetObjectItemCaseSensitive(services, "telnet");
|
||||
if (s) {
|
||||
if (!cJSON_IsObject(s)) {
|
||||
UC_LOG_ERR("Unexpected type of services:telnet: Object expected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON *enable = cJSON_GetObjectItemCaseSensitive(s, "enable");
|
||||
if (enable && !cJSON_IsBool(enable)) {
|
||||
UC_LOG_ERR("Unexpected type of services:telnet:enable: Boolean expected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfg->enabled_services_cfg.telnet.enabled = cJSON_IsTrue(enable);
|
||||
}
|
||||
|
||||
s = cJSON_GetObjectItemCaseSensitive(services, "http");
|
||||
if (s) {
|
||||
if (!cJSON_IsObject(s)) {
|
||||
UC_LOG_ERR("Unexpected type of services:http: Object expected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON *enable = cJSON_GetObjectItemCaseSensitive(s, "enable");
|
||||
if (enable && !cJSON_IsBool(enable)) {
|
||||
UC_LOG_ERR("Unexpected type of services:http:enable: Boolean expected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfg->enabled_services_cfg.http.enabled = cJSON_IsTrue(enable);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1353,7 +1700,7 @@ static int cfg_switch_ieee8021x_parse(cJSON *sw, struct plat_cfg *cfg)
|
||||
/* It's safe to check against NULL cJSON obj.
|
||||
* In case if option is missing - defaulting to 'false' is OK for us.
|
||||
*/
|
||||
cfg->ieee8021x_is_auth_ctrl_enabled = cJSON_IsTrue(auth_ctrl_enabled);
|
||||
cfg->ieee8021x.is_auth_ctrl_enabled = cJSON_IsTrue(auth_ctrl_enabled);
|
||||
radius = cJSON_GetObjectItemCaseSensitive(ieee8021x, "radius");
|
||||
|
||||
if (radius && !cJSON_IsArray(radius)) {
|
||||
@@ -2511,6 +2858,10 @@ static void script_handle(cJSON **rpc)
|
||||
UC_LOG_ERR("script message missing 'uri' parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
script_reply(0, "pending", id);
|
||||
UC_LOG_DBG("Script requested OK (pending. Waiting for plat to execute)\n");
|
||||
|
||||
memset(&file_path[0], 0, sizeof(file_path));
|
||||
if (plat_diagnostic(&file_path[0])) {
|
||||
UC_LOG_ERR("Script failed\n");
|
||||
@@ -2518,9 +2869,6 @@ static void script_handle(cJSON **rpc)
|
||||
return;
|
||||
}
|
||||
|
||||
script_reply(0, "pending", id);
|
||||
UC_LOG_DBG("Script requested OK\n");
|
||||
|
||||
/* Poll upgrade state - start periodical. */
|
||||
while (access(file_path, F_OK))
|
||||
sleep(1);
|
||||
@@ -2766,14 +3114,135 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int state_fill_transceiver_info(cJSON *root,
|
||||
struct plat_port_transceiver_info *info)
|
||||
{
|
||||
char *form_factor[] = {
|
||||
[UCENTRAL_SFP_FORM_FACTOR_NA] = "",
|
||||
[UCENTRAL_SFP_FORM_FACTOR_SFP] = "SFP",
|
||||
[UCENTRAL_SFP_FORM_FACTOR_SFP_PLUS] = "SFP+",
|
||||
[UCENTRAL_SFP_FORM_FACTOR_SFP_28] = "SFP28",
|
||||
[UCENTRAL_SFP_FORM_FACTOR_SFP_DD] = "SFP-DD",
|
||||
[UCENTRAL_SFP_FORM_FACTOR_QSFP] = "QSFP",
|
||||
[UCENTRAL_SFP_FORM_FACTOR_QSFP_PLUS] = "QSFP+",
|
||||
[UCENTRAL_SFP_FORM_FACTOR_QSFP_28] = "QSFP28",
|
||||
[UCENTRAL_SFP_FORM_FACTOR_QSFP_DD] = "QSFP-DD"
|
||||
};
|
||||
char *link_mode[] = {
|
||||
[UCENTRAL_SFP_LINK_MODE_NA] = "",
|
||||
[UCENTRAL_SFP_LINK_MODE_1000_X] = "1G",
|
||||
[UCENTRAL_SFP_LINK_MODE_2500_X] = "2.5G",
|
||||
[UCENTRAL_SFP_LINK_MODE_4000_SR] = "4G SR",
|
||||
[UCENTRAL_SFP_LINK_MODE_10G_SR] = "10G SR",
|
||||
[UCENTRAL_SFP_LINK_MODE_25G_SR] = "25G SR",
|
||||
[UCENTRAL_SFP_LINK_MODE_40G_SR] = "40G SR",
|
||||
[UCENTRAL_SFP_LINK_MODE_50G_SR] = "50G SR",
|
||||
[UCENTRAL_SFP_LINK_MODE_100G_SR] = "100G SR"
|
||||
};
|
||||
cJSON *supp_modes, *mode;
|
||||
size_t i;
|
||||
|
||||
if (!cJSON_AddStringToObject(root, "vendor-name",
|
||||
info->vendor_name))
|
||||
goto err;
|
||||
if (!cJSON_AddStringToObject(root, "part-number",
|
||||
info->part_number))
|
||||
goto err;
|
||||
if (!cJSON_AddStringToObject(root, "serial-number",
|
||||
info->serial_number))
|
||||
goto err;
|
||||
if (!cJSON_AddStringToObject(root, "revision",
|
||||
info->revision))
|
||||
goto err;
|
||||
if (!cJSON_AddNumberToObject(root, "temperature",
|
||||
info->temperature))
|
||||
goto err;
|
||||
if (!cJSON_AddNumberToObject(root, "tx-optical-power",
|
||||
info->tx_optical_power))
|
||||
goto err;
|
||||
if (!cJSON_AddNumberToObject(root, "rx-optical-power",
|
||||
info->rx_optical_power))
|
||||
goto err;
|
||||
if (!cJSON_AddNumberToObject(root, "max-module-power",
|
||||
info->max_module_power))
|
||||
goto err;
|
||||
if (!cJSON_AddStringToObject(root, "form-factor",
|
||||
form_factor[info->form_factor]))
|
||||
goto err;
|
||||
if (!(supp_modes = cJSON_AddArrayToObject(root, "supported-link-modes")))
|
||||
goto err;
|
||||
for (i = 0; i < info->num_supported_link_modes; i++) {
|
||||
if (!(mode = cJSON_CreateString(link_mode[info->supported_link_modes[i]])))
|
||||
goto err;
|
||||
if (!cJSON_AddItemToArray(supp_modes, mode)) {
|
||||
cJSON_Delete(mode);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int state_fill_interface_multicast(cJSON *root, struct plat_port_vlan *vlan)
|
||||
{
|
||||
cJSON *igmp, *enabled_groups, *group, *outgoing_ports;
|
||||
struct plat_ports_list *port_node = NULL;
|
||||
char ip_addr[] = {"255.255.255.255"};
|
||||
int ret = -1;
|
||||
size_t idx;
|
||||
|
||||
if (!vlan->igmp.exist)
|
||||
return 0;
|
||||
|
||||
igmp = cJSON_AddObjectToObject(root, "igmp");
|
||||
enabled_groups = cJSON_AddArrayToObject(igmp, "enabled-groups");
|
||||
if (!igmp || !enabled_groups)
|
||||
goto err;
|
||||
|
||||
for (idx = 0; idx < vlan->igmp.num_groups; idx++) {
|
||||
if (!(group = cJSON_CreateObject()))
|
||||
goto err;
|
||||
|
||||
if (!inet_ntop(AF_INET, &vlan->igmp.groups[idx].addr,
|
||||
ip_addr, sizeof(ip_addr)))
|
||||
goto err;
|
||||
|
||||
if (!(cJSON_AddStringToObject(group, "address", ip_addr)))
|
||||
goto err;
|
||||
|
||||
if (!(outgoing_ports = cJSON_AddArrayToObject(group, "egress-ports")))
|
||||
goto err;
|
||||
|
||||
UCENTRAL_LIST_FOR_EACH_MEMBER(
|
||||
port_node,
|
||||
&vlan->igmp.groups[idx].egress_ports_list) {
|
||||
if (!cJSON_AddItemToArray(outgoing_ports, cJSON_CreateString(port_node->name)))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!cJSON_AddItemToArray(enabled_groups, group))
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int state_fill_interfaces_data(cJSON *interfaces,
|
||||
struct plat_state_info *state)
|
||||
{
|
||||
char location[] = { "/interfaces/XXXX" };
|
||||
char vlan_name[] = { "VlanXXXX" };
|
||||
cJSON *dns_servers;
|
||||
cJSON *transceiver;
|
||||
cJSON *interface;
|
||||
cJSON *multicast;
|
||||
cJSON *counters;
|
||||
cJSON *clients;
|
||||
cJSON *ipv4;
|
||||
uint16_t id;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
@@ -2807,6 +3276,16 @@ static int state_fill_interfaces_data(cJSON *interfaces,
|
||||
if (!ipv4)
|
||||
goto err;
|
||||
|
||||
if (state->port_info[i].has_transceiver_info) {
|
||||
transceiver = cJSON_AddObjectToObject(interface, "transceiver-info");
|
||||
if (!transceiver)
|
||||
goto err;
|
||||
ret = state_fill_transceiver_info(transceiver,
|
||||
&state->port_info[i].transceiver_info);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = state_fill_interface_clients(clients,
|
||||
&state->port_info[i]);
|
||||
if (ret)
|
||||
@@ -2832,23 +3311,46 @@ static int state_fill_interfaces_data(cJSON *interfaces,
|
||||
}
|
||||
|
||||
/* TBD: find out (?) proper <location> */
|
||||
{
|
||||
char location[] = { "/interfaces/XXXX" };
|
||||
uint16_t pid;
|
||||
NAME_TO_PID(&id, state->port_info[i].name);
|
||||
sprintf(location, "/interfaces/%hu", id);
|
||||
|
||||
NAME_TO_PID(&pid, state->port_info[i].name);
|
||||
sprintf(location, "/interfaces/%hu", pid);
|
||||
|
||||
if (!cJSON_AddStringToObject(interface, "location",
|
||||
location))
|
||||
goto err;
|
||||
}
|
||||
if (!cJSON_AddStringToObject(interface, "location",
|
||||
location))
|
||||
goto err;
|
||||
|
||||
if (!jobj_u64_set(interface, "uptime",
|
||||
state->system_info.uptime))
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)state->vlan_info_count; i++) {
|
||||
interface = cJSON_CreateObject();
|
||||
if (!interface || !cJSON_AddItemToArray(interfaces, interface))
|
||||
goto err;
|
||||
|
||||
clients = cJSON_AddArrayToObject(interface, "clients");
|
||||
counters = cJSON_AddObjectToObject(interface, "counters");
|
||||
dns_servers = cJSON_AddArrayToObject(interface, "dns_servers");
|
||||
ipv4 = cJSON_AddObjectToObject(interface, "ipv4");
|
||||
multicast = cJSON_AddObjectToObject(interface, "multicast");
|
||||
if (!clients || !counters || !dns_servers || !ipv4 || !multicast)
|
||||
goto err;
|
||||
|
||||
ret = state_fill_interface_multicast(multicast, &state->vlan_info[i]);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
sprintf(location, "/SVI/%u", state->vlan_info[i].id);
|
||||
sprintf(vlan_name, "Vlan%u", state->vlan_info[i].id);
|
||||
|
||||
if (!cJSON_AddStringToObject(interface, "name", vlan_name))
|
||||
goto err;
|
||||
if (!cJSON_AddStringToObject(interface, "location", location))
|
||||
goto err;
|
||||
if (!jobj_u64_set(interface, "uptime", state->system_info.uptime))
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return -1;
|
||||
@@ -3157,16 +3659,16 @@ static int
|
||||
state_fill_unit_poe_data(cJSON *poe, struct plat_poe_state *poe_state_info)
|
||||
{
|
||||
|
||||
if (!cJSON_AddNumberToObject(poe, "max-power-budget",
|
||||
poe_state_info->max_power_budget))
|
||||
if (!jobj_u64_set(poe, "max-power-budget",
|
||||
poe_state_info->max_power_budget))
|
||||
goto err;
|
||||
|
||||
if (!cJSON_AddNumberToObject(poe, "power-consumed",
|
||||
poe_state_info->power_consumed))
|
||||
if (!jobj_u64_set(poe, "power-consumed",
|
||||
poe_state_info->power_consumed))
|
||||
goto err;
|
||||
|
||||
if (!cJSON_AddNumberToObject(poe, "power-threshold",
|
||||
poe_state_info->power_threshold))
|
||||
if (!jobj_u64_set(poe, "power-threshold",
|
||||
poe_state_info->power_threshold))
|
||||
goto err;
|
||||
|
||||
if (!cJSON_AddStringToObject(poe, "power-status",
|
||||
@@ -3178,8 +3680,51 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
state_fill_unit_ieee8021x_global_counters(cJSON *ieee8021x,
|
||||
struct plat_iee8021x_coa_counters *c)
|
||||
{
|
||||
cJSON *das, *stats;
|
||||
|
||||
das = cJSON_AddObjectToObject(ieee8021x, "dynamic-authorization");
|
||||
if (!das)
|
||||
return -1;
|
||||
|
||||
stats = cJSON_AddObjectToObject(das, "stats");
|
||||
if (!stats)
|
||||
return -1;
|
||||
|
||||
if (!jobj_u64_set(stats, "coa_req_received",
|
||||
c->coa_req_received))
|
||||
return -1;
|
||||
if (!jobj_u64_set(stats, "coa_ack_sent",
|
||||
c->coa_ack_sent))
|
||||
return -1;
|
||||
if (!jobj_u64_set(stats, "coa_nak_sent",
|
||||
c->coa_nak_sent))
|
||||
return -1;
|
||||
if (!jobj_u64_set(stats, "coa_ignored",
|
||||
c->coa_ignored))
|
||||
return -1;
|
||||
if (!jobj_u64_set(stats, "coa_wrong_attr",
|
||||
c->coa_wrong_attr))
|
||||
return -1;
|
||||
if (!jobj_u64_set(stats, "coa_wrong_attr_value",
|
||||
c->coa_wrong_attr_value))
|
||||
return -1;
|
||||
if (!jobj_u64_set(stats, "coa_wrong_session_context",
|
||||
c->coa_wrong_session_context))
|
||||
return -1;
|
||||
if (!jobj_u64_set(stats, "administratively_prohibited_req",
|
||||
c->coa_administratively_prohibited_req))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int state_fill_unit_data(cJSON *unit, struct plat_state_info *state)
|
||||
{
|
||||
cJSON *ieee8021x;
|
||||
cJSON *loadArr;
|
||||
cJSON *memory;
|
||||
cJSON *poe;
|
||||
@@ -3215,6 +3760,12 @@ static int state_fill_unit_data(cJSON *unit, struct plat_state_info *state)
|
||||
if (!poe || state_fill_unit_poe_data(poe, &state->poe_state))
|
||||
goto err;
|
||||
|
||||
ieee8021x = cJSON_AddObjectToObject(unit, "ieee8021x");
|
||||
if (!ieee8021x ||
|
||||
state_fill_unit_ieee8021x_global_counters(ieee8021x,
|
||||
&state->ieee8021x_global_coa_counters))
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
||||
Reference in New Issue
Block a user