void ivs_cli_init(const char *path) { ucli_init(); unlink(path); listen_socket = socket(AF_UNIX, SOCK_STREAM, 0); if (listen_socket < 0) { perror("socket (CLI)"); abort(); } struct sockaddr_un saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sun_family = AF_UNIX; strcpy(saddr.sun_path, path); if (bind(listen_socket, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind (CLI)"); abort(); } if (listen(listen_socket, LISTEN_BACKLOG) < 0) { perror("listen (CLI)"); abort(); } indigo_error_t rv = ind_soc_socket_register(listen_socket, listen_callback, NULL); if (rv < 0) { AIM_DIE("Failed to register CLI socket: %s", indigo_strerror(rv)); } }
static void listen_callback( int socket_id, void *cookie, int read_ready, int write_ready, int error_seen) { AIM_LOG_TRACE("Accepting CLI client"); int fd; if ((fd = accept(listen_socket, NULL, NULL)) < 0) { AIM_LOG_ERROR("Failed to accept on CLI socket: %s", strerror(errno)); return; } struct client *client = aim_zmalloc(sizeof(*client)); client->fd = fd; client->write_pvs = aim_pvs_buffer_create(); client->ucli = ucli_create("ivs", NULL, NULL); indigo_error_t rv = ind_soc_socket_register(fd, client_callback, client); if (rv < 0) { AIM_LOG_ERROR("Failed to register CLI client socket: %s", indigo_strerror(rv)); return; } }
void ind_ovs_port_init(void) { int nlerr; route_cache_sock = nl_socket_alloc(); if (route_cache_sock == NULL) { LOG_ERROR("nl_socket_alloc failed"); abort(); } if ((nlerr = nl_cache_mngr_alloc(route_cache_sock, NETLINK_ROUTE, 0, &route_cache_mngr)) < 0) { LOG_ERROR("nl_cache_mngr_alloc failed: %s", nl_geterror(nlerr)); abort(); } if ((nlerr = nl_cache_mngr_add(route_cache_mngr, "route/link", link_change_cb, NULL, &link_cache)) < 0) { LOG_ERROR("nl_cache_mngr_add failed: %s", nl_geterror(nlerr)); abort(); } if (ind_soc_socket_register(nl_cache_mngr_get_fd(route_cache_mngr), (ind_soc_socket_ready_callback_f)route_cache_mngr_socket_cb, NULL) < 0) { LOG_ERROR("failed to register socket"); abort(); } netlink_callbacks = nl_cb_alloc(NL_CB_DEFAULT); if (netlink_callbacks == NULL) { LOG_ERROR("failed to allocate netlink callbacks"); abort(); } }
int main(int argc, char* argv[]) { ind_soc_config_t config = {0}; int fds[2]; printf("Init returned %d\n", ind_soc_init(&config)); /* Should be called once */ ind_soc_timer_event_register(timer_callback, NULL, IND_SOC_TIMER_IMMEDIATE); ind_soc_select_and_run(10); INDIGO_ASSERT(timer_called); timer_called = 0; ind_soc_select_and_run(1000); INDIGO_ASSERT(!timer_called); ind_soc_timer_event_register(timer_callback, NULL, 100); ind_soc_select_and_run(1000); INDIGO_ASSERT(timer_called); timer_called = 0; ind_soc_timer_event_register(timer_callback_repeat, NULL, 100); ind_soc_select_and_run(1000); INDIGO_ASSERT(timer_called >= 9); ind_soc_timer_event_unregister(timer_callback_repeat, NULL); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { perror("socketpair"); abort(); } INDIGO_ASSERT(ind_soc_socket_register(fds[0], socket_callback, NULL) == 0); INDIGO_ASSERT(ind_soc_socket_register(fds[1], socket_callback, NULL) == 0); ind_soc_data_out_ready(fds[0]); ind_soc_data_out_ready(fds[1]); /* Do stuff for 3 seconds */ ind_soc_select_and_run(3000); INDIGO_ASSERT(socket_called > 0); INDIGO_ASSERT(sock_read_seen > 0); INDIGO_ASSERT(sock_write_seen > 0); return 0; }
static inline void cxn_state_set(connection_t *cxn, indigo_cxn_state_t new_state) { indigo_cxn_state_t old_state; old_state = CONNECTION_STATE(cxn); if (old_state == new_state) { LOG_TRACE(cxn, "Non-state change in %s", CXN_STATE_NAME(new_state)); return; } LOG_INFO(cxn, "%s->%s", CXN_STATE_NAME(old_state), CXN_STATE_NAME(new_state)); /**************************************************************** * * Verify pre-conditions * * @fixme Check here for illegal state transitions * ****************************************************************/ switch (new_state) { case INDIGO_CXN_S_DISCONNECTED: /* If moving to disconnected, must be closing (or disconnected) */ if ((old_state != INDIGO_CXN_S_CLOSING)) { LOG_ERROR(cxn, "Error in cxn SM: disconnected from %s", CXN_STATE_NAME(old_state)); /* Clean up and hope for the best */ } break; default: break; } /**************************************************************** * * Exit conditions for old state * ****************************************************************/ switch (old_state) { case INDIGO_CXN_S_CLOSING: ind_soc_timer_event_unregister(cxn_closing_timeout, (void *)cxn); break; case INDIGO_CXN_S_CONNECTING: if (!CXN_LOCAL(cxn)) { ind_soc_timer_event_unregister(cxn_connecting_timeout, (void *)cxn); } break; default: break; } /**************************************************************** * * Process change to new state * ****************************************************************/ /* Change state of connection */ cxn->status.state = new_state; /* External notification of state change before processing */ ind_cxn_status_change(cxn); /* Post-processing of state transition. */ switch (new_state) { case INDIGO_CXN_S_DISCONNECTED: if (cxn->flags & CXN_TO_BE_REMOVED) { LOG_INFO(cxn, "Completing cxn removal"); cxn->active = 0; } else if (CXN_LOCAL(cxn)) { cxn->active = 0; } ind_cxn_disconnected_init(cxn); break; case INDIGO_CXN_S_CONNECTING: /* Register with socket manager */ ind_soc_socket_register(cxn->sd, indigo_cxn_socket_ready_callback, cxn); ind_cxn_send_hello(cxn); if (CXN_LOCAL(cxn)) { /* Recursive call; transition to connected */ cxn_state_set(cxn, INDIGO_CXN_S_HANDSHAKE_COMPLETE); } else { ind_soc_timer_event_register(cxn_connecting_timeout, (void *)cxn, CXN_STATE_TIMEOUT(new_state)); } break; case INDIGO_CXN_S_CLOSING: #if defined(OF_OBJECT_TRACKING) #define VERBOSE_LOG_ENABLED 1 /* @FIXME Check log level */ if ((cxn->outstanding_ops) && VERBOSE_LOG_ENABLED) { biglist_t *elt; of_object_t *obj; LOG_VERBOSE(cxn, "Closing connnection with outstanding ops"); BIGLIST_FOREACH_DATA(elt, cxn->outstanding_ops, of_object_t *, obj) { of_object_track_output(obj, (loci_writer_f)aim_printf, AIM_LOG_STRUCT_POINTER->pvs); } } #endif ind_soc_timer_event_unregister(periodic_keepalive, (void *)cxn); ind_soc_timer_event_register(cxn_closing_timeout, (void *)cxn, CXN_STATE_TIMEOUT(new_state)); cleanup_disconnect(cxn); break; case INDIGO_CXN_S_HANDSHAKE_COMPLETE: if (cxn->keepalive.period_ms > 0) { /* Set up periodic echo request */ ind_soc_timer_event_register(periodic_keepalive, (void *)cxn, cxn->keepalive.period_ms); } break; default: break; }
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; }
static void test_socket(void) { int fds[2]; struct sock_counters counters[2]; indigo_time_t start_time, end_time; struct itimerval itv; signal(SIGALRM, sigalrm); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { perror("socketpair"); abort(); } INDIGO_ASSERT(ind_soc_socket_register(fds[0], socket_callback, &counters[0]) == 0); INDIGO_ASSERT(ind_soc_socket_register(fds[1], socket_callback, &counters[1]) == 0); /* No events ready */ memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 0); INDIGO_ASSERT(counters[1].write == 0); /* Write one byte to fds[0] */ ind_soc_data_out_ready(fds[0]); memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 1); INDIGO_ASSERT(counters[1].read == 0); INDIGO_ASSERT(counters[1].write == 0); /* Read one byte from fds[1] */ memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 1); INDIGO_ASSERT(counters[1].write == 0); /* Write one byte to each of fds[0] and fds[1] */ ind_soc_data_out_ready(fds[0]); ind_soc_data_out_ready(fds[1]); memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 1); INDIGO_ASSERT(counters[1].read == 0); INDIGO_ASSERT(counters[1].write == 1); /* Read one byte from each of fds[0] and fds[1] */ memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 1); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 1); INDIGO_ASSERT(counters[1].write == 0); /* Write one byte to fds[0] */ ind_soc_data_out_ready(fds[0]); memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 1); INDIGO_ASSERT(counters[1].read == 0); INDIGO_ASSERT(counters[1].write == 0); /* Pause data in from fds[1], expect no reads */ ind_soc_data_in_pause(fds[1]); memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 0); INDIGO_ASSERT(counters[1].write == 0); /* Resume data in from fds[1] */ ind_soc_data_in_resume(fds[1]); memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 1); INDIGO_ASSERT(counters[1].write == 0); /* Block for some time with no events */ memset(counters, 0, sizeof(counters)); start_time = INDIGO_CURRENT_TIME; ind_soc_select_and_run(100); end_time = INDIGO_CURRENT_TIME; INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 0); INDIGO_ASSERT(counters[1].write == 0); INDIGO_ASSERT((end_time - start_time) >= 100 && (end_time - start_time) < 200); /* Block for some time until SIGALRM, which causes read ready on fd[1] */ memset(counters, 0, sizeof(counters)); memset(&itv, 0, sizeof(itv)); sigalrm_write_fd = fds[0]; itv.it_value.tv_usec = 100*1000; setitimer(ITIMER_REAL, &itv, NULL); ind_soc_select_and_run(200); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 1); INDIGO_ASSERT(counters[1].write == 0); INDIGO_ASSERT(ind_soc_socket_unregister(fds[0]) == 0); INDIGO_ASSERT(ind_soc_socket_unregister(fds[1]) == 0); close(fds[0]); close(fds[1]); }
/* Test add/remove of sockets */ static void test_socket_mgmt(void) { int fds[2]; struct sock_counters counters[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { perror("socketpair"); abort(); } /* Unregistering a not-registered socket should fail */ INDIGO_ASSERT(ind_soc_socket_unregister(fds[0]) < 0); /* Adding and then unregistering a socket should succeed */ INDIGO_ASSERT(ind_soc_socket_register(fds[0], socket_callback, &counters[0]) == 0); INDIGO_ASSERT(ind_soc_socket_unregister(fds[0]) == 0); /* Trying to unregister twice should fail */ INDIGO_ASSERT(ind_soc_socket_unregister(fds[0]) < 0); /* Trying to register twice should fail */ INDIGO_ASSERT(ind_soc_socket_register(fds[0], socket_callback, &counters[0]) == 0); INDIGO_ASSERT(ind_soc_socket_register(fds[0], socket_callback, &counters[0]) < 0); /* Add another socket, then remove the first */ INDIGO_ASSERT(ind_soc_socket_register(fds[1], socket_callback, &counters[1]) == 0); INDIGO_ASSERT(ind_soc_socket_unregister(fds[0]) == 0); /* Write one byte to fds[1] */ ind_soc_data_out_ready(fds[1]); memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 0); INDIGO_ASSERT(counters[1].write == 1); /* Expect no events from the not-registered fds[0] */ memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 0); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 0); INDIGO_ASSERT(counters[1].write == 0); /* Register fds[0] and expect a read event */ INDIGO_ASSERT(ind_soc_socket_register(fds[0], socket_callback, &counters[0]) == 0); memset(counters, 0, sizeof(counters)); ind_soc_select_and_run(0); INDIGO_ASSERT(counters[0].read == 1); INDIGO_ASSERT(counters[0].write == 0); INDIGO_ASSERT(counters[1].read == 0); INDIGO_ASSERT(counters[1].write == 0); INDIGO_ASSERT(ind_soc_socket_unregister(fds[0]) == 0); INDIGO_ASSERT(ind_soc_socket_unregister(fds[1]) == 0); close(fds[0]); close(fds[1]); }