void ind_cxn_bundle_add_handle(connection_t *cxn, of_object_t *obj) { uint32_t bundle_id; uint16_t flags; of_octets_t data; of_bundle_add_msg_bundle_id_get(obj, &bundle_id); of_bundle_add_msg_flags_get(obj, &flags); of_bundle_add_msg_data_get(obj, &data); bundle_t *bundle = find_bundle(cxn, bundle_id); if (bundle == NULL) { indigo_cxn_send_error_reply( cxn->cxn_id, obj, OF_ERROR_TYPE_BUNDLE_FAILED, OFPBFC_BAD_ID); return; } /* Validate length */ if (data.bytes < OF_MESSAGE_HEADER_LENGTH || data.bytes != of_message_length_get(data.data)) { indigo_cxn_send_error_reply( cxn->cxn_id, obj, OF_ERROR_TYPE_BUNDLE_FAILED, OFPBFC_MSG_BAD_LEN); AIM_LOG_WARN("Inconsistent bundled message length", bundle->id); return; } /* Limit number of messages in the bundle */ if (bundle->count >= OFCONNECTIONMANAGER_CONFIG_MAX_BUNDLE_MSGS) { indigo_cxn_send_error_reply( cxn->cxn_id, obj, OF_ERROR_TYPE_BUNDLE_FAILED, OFPBFC_MSG_TOO_MANY); AIM_LOG_WARN("Exceeded maximum number (%u) of messages in bundle %u", OFCONNECTIONMANAGER_CONFIG_MAX_BUNDLE_MSGS, bundle->id); return; } /* Limit amount of memory used by the bundle */ if ((bundle->bytes + data.bytes) > OFCONNECTIONMANAGER_CONFIG_MAX_BUNDLE_BYTES) { indigo_cxn_send_error_reply( cxn->cxn_id, obj, OF_ERROR_TYPE_BUNDLE_FAILED, OFPBFC_MSG_TOO_MANY); AIM_LOG_WARN("Exceeded maximum size (%u bytes) of messages in bundle %u", OFCONNECTIONMANAGER_CONFIG_MAX_BUNDLE_BYTES, bundle->id); return; } if (bundle->count == bundle->allocated) { /* Resize array */ uint32_t new_allocated = (bundle->allocated == 0 ? 1 : bundle->allocated * 2); bundle->msgs = aim_realloc(bundle->msgs, sizeof(*bundle->msgs) * new_allocated); bundle->allocated = new_allocated; } bundle->msgs[bundle->count++] = aim_memdup(data.data, data.bytes); bundle->bytes += data.bytes; }
int onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* rv) { *rv = fans__[ONLP_OID_ID_GET(id)]; rv->caps |= ONLP_FAN_CAPS_GET_RPM; int len; char direction[16] = {0}; int fid = ONLP_OID_ID_GET(id); /* Read the current airflow direction */ onlp_file_read((uint8_t*)direction, sizeof(direction), &len, SYS_HWMON_PREFIX "/fan_dir"); #define FAN_DIR_F2B "front-to-back" #define FAN_DIR_B2F "back-to-front" if(!strncmp(direction, FAN_DIR_F2B, strlen(FAN_DIR_F2B))) { rv->status |= ONLP_FAN_STATUS_F2B; rv->caps |= ONLP_FAN_CAPS_F2B; } else if(!strncmp(direction, FAN_DIR_B2F, strlen(FAN_DIR_B2F))) { rv->status |= ONLP_FAN_STATUS_B2F; rv->caps |= ONLP_FAN_CAPS_B2F; } else { AIM_LOG_WARN("Invalid fan direction: '%s'", direction); } switch(fid) { case FAN_ID_FAN1: case FAN_ID_FAN2: case FAN_ID_FAN3: case FAN_ID_FAN4: { if(rv->status & ONLP_FAN_STATUS_F2B) { return sys_fan_info_get__(rv, fid); } if(rv->status & ONLP_FAN_STATUS_B2F) { return sys_fan_info_get__(rv, fid+4); } return ONLP_STATUS_E_INTERNAL; } case FAN_ID_FAN5: case FAN_ID_FAN6: { return psu_fan_info_get__(rv, fid); } } return ONLP_STATUS_E_INVALID; }
static void ind_cxn_cfg_commit(void) { aim_log_t *lobj; int i; if ((lobj = aim_log_find("ofconnectionmanager")) == NULL) { AIM_LOG_WARN("Could not find log module"); } else { lobj->common_flags = staged_config.log_flags; } for (i = 0; i < staged_config.num_controllers; i++) { struct controller *c = &staged_config.controllers[i]; const struct controller *old_controller; int rv; indigo_cxn_params_tcp_over_ipv4_t *proto = &c->proto.tcp_over_ipv4; AIM_LOG_INFO("controller %d: %s:%hu", i, proto->controller_ip, proto->controller_port); /* Keep existing connections to the same controller. */ if ((old_controller = find_controller(¤t_config, &c->proto))) { c->cxn_id = old_controller->cxn_id; /* TODO apply keepalive_period to existing connection. */ continue; } rv = indigo_cxn_connection_add(&c->proto, &c->config, &c->cxn_id); if (rv != 0) { AIM_LOG_ERROR("failed to add controller connection %d: %s:%u", i, proto->controller_ip, proto->controller_port); } } /* Remove connections that don't exist in the new configuration. */ for (i = 0; i < current_config.num_controllers; i++) { const struct controller *c = ¤t_config.controllers[i]; if (!find_controller(&staged_config, &c->proto)) { (void) indigo_cxn_connection_remove(c->cxn_id); } } /* Save config so we can diff the controllers next time */ current_config = staged_config; }
static void ind_core_cfg_commit(void) { aim_log_t *lobj; if ((lobj = aim_log_find("ofstatemanager")) == NULL) { AIM_LOG_WARN("Could not find log module"); } else { lobj->common_flags = staged_config.log_flags; } /* Set whether or not changed */ (void)ind_core_hw_desc_set(staged_config.hw_desc); (void)ind_core_sw_desc_set(staged_config.sw_desc); (void)ind_core_dp_desc_set(staged_config.dp_desc); (void)ind_core_mfr_desc_set(staged_config.mfr_desc); (void)ind_core_serial_num_set(staged_config.serial_num); (void)indigo_core_dpid_set(staged_config.dpid); (void)indigo_core_disconnected_mode_set(staged_config.disconnected_mode); }
void ind_core_bsn_table_set_buckets_size_handler(of_object_t *_obj, indigo_cxn_id_t cxn_id) { of_bsn_table_set_buckets_size_t *obj = _obj; uint16_t table_id; uint32_t buckets_size; indigo_error_t rv; of_bsn_table_set_buckets_size_table_id_get(obj, &table_id); of_bsn_table_set_buckets_size_buckets_size_get(obj, &buckets_size); rv = ft_set_checksum_buckets_size(ind_core_ft, table_id, buckets_size); if (rv < 0) { AIM_LOG_WARN("Failed to set table %d checksum buckets size to %d: %s", table_id, buckets_size, indigo_strerror(rv)); indigo_cxn_send_error_reply(cxn_id, obj, OF_ERROR_TYPE_BAD_REQUEST, OF_REQUEST_FAILED_EPERM); } }
static void ind_cxn_cfg_commit(void) { aim_log_t *lobj; int i, enable; if (staged_config.valid != true) return; /* Commit config only if connection manager is enabled. */ (void) ind_cxn_enable_get(&enable); if (!enable) return; if ((lobj = aim_log_find("ofconnectionmanager")) == NULL) { AIM_LOG_WARN("Could not find log module"); } else { lobj->common_flags = staged_config.log_flags; } /* configure TLS before parsing controller configs */ (void) indigo_cxn_config_tls(staged_config.cipher_list, staged_config.ca_cert, staged_config.switch_cert, staged_config.switch_priv_key, staged_config.exp_controller_suffix); for (i = 0; i < staged_config.num_controllers; i++) { struct controller *c = &staged_config.controllers[i]; const struct controller *old_controller; int rv; char desc[256]; ind_cxn_proto_ip_string(&c->proto, desc, sizeof(desc)); AIM_LOG_INFO("controller %d: %s", i, desc); /* Keep existing connections to the same controller. */ if ((old_controller = find_controller(¤t_config, &c->proto))) { c->controller_id = old_controller->controller_id; /* TODO apply keepalive_period to existing connection. */ continue; } rv = indigo_controller_add(&c->proto, &c->config, &c->controller_id); if (rv != 0) { AIM_LOG_ERROR("failed to add controller connection %d: %s", i, desc); } } /* Remove controller's that don't exist in the new configuration. */ for (i = 0; i < current_config.num_controllers; i++) { const struct controller *c = ¤t_config.controllers[i]; if (!find_controller(&staged_config, &c->proto)) { (void) indigo_controller_remove(c->controller_id); } } /* Save config so we can diff the controllers next time */ current_config = staged_config; staged_config.valid = false; }
static void client_callback( int socket_id, void *cookie, int read_ready, int write_ready, int error_seen) { struct client *client = cookie; AIM_ASSERT(socket_id == client->fd); if (error_seen) { int socket_error = 0; socklen_t len = sizeof(socket_error); getsockopt(socket_id, SOL_SOCKET, SO_ERROR, &socket_error, &len); AIM_LOG_INFO("Error seen on CLI socket: %s", strerror(socket_error)); destroy_client(client); return; } if (read_ready) { int c; if ((c = read(client->fd, client->read_buffer+client->read_buffer_offset, READ_BUFFER_SIZE - client->read_buffer_offset)) < 0) { AIM_LOG_ERROR("read failed: %s", strerror(errno)); return; } client->read_buffer_offset += c; if (c == 0) { /* Peer has shutdown their write side */ if (client->write_buffer_len == 0 && aim_pvs_buffer_size(client->write_pvs) == 0) { destroy_client(client); } else { /* We'll destroy the client once we've finished writing to it */ ind_soc_data_in_pause(client->fd); client->read_finished = true; } return; } /* Process each complete line */ char *newline; char *start = client->read_buffer; int remaining = client->read_buffer_offset; while ((newline = memchr(start, '\n', remaining))) { *newline = '\0'; ucli_dispatch_string(client->ucli, client->write_pvs, start); remaining -= newline - start + 1; start = newline + 1; } /* Move incomplete line (which may be empty) to the beginning of the read buffer */ if (client->read_buffer != start) { memmove(client->read_buffer, start, remaining); client->read_buffer_offset = remaining; } else if (client->read_buffer_offset == READ_BUFFER_SIZE) { AIM_LOG_WARN("Disconnecting CLI client due to too-long line"); destroy_client(client); return; } if (aim_pvs_buffer_size(client->write_pvs) > 0) { ind_soc_data_out_ready(socket_id); } } if (write_ready) { /* Copy PVS data into our write buffer and reset PVS */ if (client->write_buffer == NULL) { client->write_buffer = aim_pvs_buffer_get(client->write_pvs); client->write_buffer_len = aim_pvs_buffer_size(client->write_pvs); client->write_buffer_offset = 0; /* aim_pvs_buffer_reset has a bug, workaround it */ aim_pvs_destroy(client->write_pvs); client->write_pvs = aim_pvs_buffer_create(); } int c = send(client->fd, client->write_buffer+client->write_buffer_offset, client->write_buffer_len-client->write_buffer_offset, MSG_NOSIGNAL); if (c <= 0) { AIM_LOG_ERROR("write failed: %s", strerror(errno)); destroy_client(client); return; } client->write_buffer_offset += c; /* Free our write buffer if we're finished with it */ if (client->write_buffer_len == client->write_buffer_offset) { aim_free(client->write_buffer); client->write_buffer_len = client->write_buffer_offset = 0; client->write_buffer = NULL; if (aim_pvs_buffer_size(client->write_pvs) == 0) { ind_soc_data_out_clear(client->fd); if (client->read_finished) { destroy_client(client); } } } } }
void ind_core_bsn_flow_checksum_bucket_stats_request_handler(of_object_t *_obj, indigo_cxn_id_t cxn_id) { of_bsn_flow_checksum_bucket_stats_request_t *obj = _obj; of_bsn_flow_checksum_bucket_stats_reply_t *reply; of_list_bsn_flow_checksum_bucket_stats_entry_t entries; of_bsn_flow_checksum_bucket_stats_entry_t *entry; uint32_t xid; uint8_t table_id; ft_table_t *table; int bucket_idx; of_bsn_flow_checksum_bucket_stats_request_table_id_get(obj, &table_id); if (table_id >= FT_MAX_TABLES) { AIM_LOG_WARN("Invalid table ID %u", table_id); indigo_cxn_send_error_reply(cxn_id, obj, OF_ERROR_TYPE_BAD_REQUEST, OF_REQUEST_FAILED_EPERM); return; } table = &ind_core_ft->tables[table_id]; reply = of_bsn_flow_checksum_bucket_stats_reply_new(obj->version); AIM_TRUE_OR_DIE(reply != NULL); of_bsn_flow_checksum_bucket_stats_request_xid_get(obj, &xid); of_bsn_flow_checksum_bucket_stats_reply_xid_set(reply, xid); of_bsn_flow_checksum_bucket_stats_reply_entries_bind(reply, &entries); entry = of_bsn_flow_checksum_bucket_stats_entry_new(entries.version); AIM_TRUE_OR_DIE(entry != NULL); for (bucket_idx = 0; bucket_idx < table->checksum_buckets_size; bucket_idx++) { of_bsn_flow_checksum_bucket_stats_entry_checksum_set( entry, table->checksum_buckets[bucket_idx]); if (of_list_append(&entries, entry) < 0) { /* This entry didn't fit, send out the current message and * allocate a new one. */ of_bsn_flow_checksum_bucket_stats_reply_flags_set( reply, OF_STATS_REPLY_FLAG_REPLY_MORE); indigo_cxn_send_controller_message(cxn_id, reply); reply = of_bsn_flow_checksum_bucket_stats_reply_new(obj->version); AIM_TRUE_OR_DIE(reply != NULL); of_bsn_flow_checksum_bucket_stats_reply_xid_set(reply, xid); of_bsn_flow_checksum_bucket_stats_reply_entries_bind(reply, &entries); if (of_list_append(&entries, entry) < 0) { AIM_DIE("unexpected failure appending single bsn_flow_checksum_bucket stats entry"); } } } of_object_delete(entry); indigo_cxn_send_controller_message(cxn_id, reply); }
int onlp_sfpi_post_insert(int port, sff_info_t* info) { /* * IF any platform-programming must be performed based * on the actual SFP that was inserted (for example, custom equalizer settings) * then it should be performed by this function. * * If not custom programming must be performed, then do nothing. * This function is optional. */ int front_port=0; sfp_tranceiver_cable_type_t cable_type = SFP_TRANCEIVER_CABLE_TYPE_FIBER; switch(info->media_type) { case SFF_MEDIA_TYPE_FIBER: cable_type = SFP_TRANCEIVER_CABLE_TYPE_FIBER; break; case SFF_MEDIA_TYPE_COPPER: switch(info->length) { case 1: case 2: AIM_LOG_MSG("Port %d EQ 1M", port); cable_type = SFP_TRANCEIVER_CABLE_TYPE_COPPER_1M; break; case 3: case 4: AIM_LOG_MSG("Port %d EQ 3M", port); cable_type = SFP_TRANCEIVER_CABLE_TYPE_COPPER_3M; break; case 5: case 6: AIM_LOG_MSG("Port %d EQ 5M", port); cable_type = SFP_TRANCEIVER_CABLE_TYPE_COPPER_5M; break; case 7: AIM_LOG_MSG("Port %d EQ 7M", port); cable_type = SFP_TRANCEIVER_CABLE_TYPE_COPPER_7M; break; default: AIM_LOG_MSG("Port %d EQ 7M (MAX)", port); /* Nothing beyond 7M is supported. Best we can do is use the 7M settings. */ cable_type = SFP_TRANCEIVER_CABLE_TYPE_COPPER_7M; break; } break; default: AIM_LOG_WARN("port(%d) media_type(%d) length(%d) is not supported\r\n", port, info->media_type, info->length); return ONLP_STATUS_E_INTERNAL; } front_port=SFP_MAP_API_2_FRONT_PORT(port); if (set_active_port(front_port) < 0) { AIM_LOG_ERROR("Unable to set active port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } if (set_equalizer_type(cable_type) < 0) { AIM_LOG_ERROR("Unable to set port(%d) media_type(%d) length(%d)\r\n", port, info->media_type, info->length); return ONLP_STATUS_E_INTERNAL; } return ONLP_STATUS_OK; }
int aim_main(int argc, char *argv[]) { set_crash_handler(crash_handler); AIM_LOG_STRUCT_REGISTER(); loci_logger = ofagent_loci_logger; core_cfg.stats_check_ms = 900; parse_options(argc, argv); /* Setup logging from command line options */ if (loglevel >= LOGLEVEL_DEFAULT) { aim_log_fid_set_all(AIM_LOG_FLAG_MSG, 1); aim_log_fid_set_all(AIM_LOG_FLAG_FATAL, 1); aim_log_fid_set_all(AIM_LOG_FLAG_ERROR, 1); aim_log_fid_set_all(AIM_LOG_FLAG_WARN, 1); } if (loglevel >= LOGLEVEL_VERBOSE) { aim_log_fid_set_all(AIM_LOG_FLAG_VERBOSE, 1); } if (loglevel >= LOGLEVEL_TRACE) { aim_log_fid_set_all(AIM_LOG_FLAG_TRACE, 1); } if (use_syslog) { aim_log_pvs_set_all(aim_pvs_syslog_open("ofagent", LOG_NDELAY, LOG_DAEMON)); } create_pidfile(); AIM_LOG_MSG("Starting ofagent %s (%s %s) pid %d", ofagent_version, ofagent_build_id, ofagent_build_os, getpid()); /* Increase maximum number of file descriptors */ struct rlimit rlim = { .rlim_cur = SOCKETMANAGER_CONFIG_MAX_SOCKETS, .rlim_max = SOCKETMANAGER_CONFIG_MAX_SOCKETS }; if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { AIM_LOG_WARN("Failed to increase RLIMIT_NOFILE"); } /* Initialize all modules */ if (ind_soc_init(&soc_cfg) < 0) { AIM_LOG_FATAL("Failed to initialize Indigo socket manager"); return 1; } if (ind_cxn_init(&cxn_cfg) < 0) { AIM_LOG_FATAL("Failed to initialize Indigo connection manager"); return 1; } if (ind_core_init(&core_cfg) < 0) { AIM_LOG_FATAL("Failed to initialize Indigo core module"); return 1; } if (bcm_driver_init() < 0) { AIM_LOG_FATAL("Failed to initialize BCM driver"); return 1; } if (pipeline == NULL) { if (openflow_version == NULL || !strcmp(openflow_version, "1.0")) { pipeline = "standard-1.0"; } else if (!strcmp(openflow_version, "1.3")) { pipeline = "standard-1.3"; } else { AIM_DIE("unexpected OpenFlow version"); } } AIM_LOG_VERBOSE("Initializing forwarding pipeline '%s'", pipeline); indigo_error_t rv = pipeline_set(pipeline); if (rv < 0) { AIM_LOG_FATAL("Failed to set pipeline: %s", indigo_strerror(rv)); return 1; } if (config_filename) { ind_cfg_filename_set(config_filename); if (ind_cfg_load() < 0) { AIM_LOG_FATAL("Failed to load configuration file"); return 1; } } if (dpid) { indigo_core_dpid_set(dpid); } /* Enable all modules */ if (ind_soc_enable_set(1) < 0) { AIM_LOG_FATAL("Failed to enable Indigo socket manager"); return 1; } if (ind_cxn_enable_set(1) < 0) { AIM_LOG_FATAL("Failed to enable Indigo connection manager"); return 1; } if (ind_core_enable_set(1) < 0) { AIM_LOG_FATAL("Failed to enable Indigo core module"); return 1; } if (bcm_driver_enable_set(1) < 0) { AIM_LOG_FATAL("Failed to enable BCM driver"); return 1; } /* Add controller from command line */ { biglist_t *element; char *str; BIGLIST_FOREACH_DATA(element, controllers, char *, str) { AIM_LOG_VERBOSE("Adding controller %s", str); indigo_cxn_protocol_params_t proto; if (parse_controller(str, &proto, OF_TCP_PORT) < 0) { AIM_LOG_FATAL("Failed to parse controller string '%s'", str); return 1; } indigo_cxn_config_params_t config = { .version = OF_VERSION_1_0, .cxn_priority = 0, .local = 0, .listen = 0, .periodic_echo_ms = 2000, .reset_echo_count = 3, }; indigo_controller_id_t id; if (indigo_controller_add(&proto, &config, &id) < 0) { AIM_LOG_FATAL("Failed to add controller %s", str); return 1; } } } ind_core_mfr_desc_set(mfr_desc); snprintf(sw_desc, sizeof(sw_desc), "ofagent %s %s %s", ofagent_version, ofagent_build_id, ofagent_build_os); ind_core_sw_desc_set(sw_desc); // TODO //read_hardware_version(hw_desc); ind_core_hw_desc_set(hw_desc); char hostname[256]; char domainname[256]; if (gethostname(hostname, sizeof(hostname))) { sprintf(hostname, "(unknown)"); } if (getdomainname(domainname, sizeof(domainname))) { sprintf(domainname, "(unknown)"); } snprintf(dp_desc, sizeof(dp_desc), "%s.%s pid %d", hostname, domainname, getpid()); ind_core_dp_desc_set(dp_desc); AIM_LOG_INFO("Datapath description: %s", dp_desc); ind_core_serial_num_set(serial_num); /* The SIGHUP handler triggers sighup_callback to run in the main loop. */ if ((sighup_eventfd = eventfd(0, 0)) < 0) { AIM_LOG_FATAL("Failed to allocate eventfd"); abort(); } signal(SIGHUP, sighup); if (ind_soc_socket_register(sighup_eventfd, sighup_callback, NULL) < 0) { abort(); } /* The SIGTERM handler triggers sigterm_callback to run in the main loop. */ if ((sigterm_eventfd = eventfd(0, 0)) < 0) { AIM_LOG_FATAL("Failed to allocate eventfd"); abort(); } signal(SIGTERM, sigterm); if (ind_soc_socket_register(sigterm_eventfd, sigterm_callback, NULL) < 0) { abort(); } /* TODO Start handling upcalls */ //ind_ovs_enable(); //packet_trace_init(datapath_name); ind_soc_select_and_run(-1); AIM_LOG_MSG("Stopping ofagent %s", ofagent_version); ind_core_finish(); bcm_driver_finish(); ind_cxn_finish(); ind_soc_finish(); return 0; }