/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_id (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); assert(0 == strcmp(node->name, "id")); assert(node); assert(node->doc); assert(node->children); if ((XMLDIFF_ADD|XMLDIFF_MOD) & op) { xmlChar* text = xmlNodeListGetString(node->doc, node->children, 1); nc_verb_verbose("got string: \n%s\n", text); if (ofc_state.capable_switch_id) { free(ofc_state.capable_switch_id); } ofc_state.capable_switch_id = strdup(text); xmlFree(text); } else if (XMLDIFF_REM & op) { if (ofc_state.capable_switch_id) { free(ofc_state.capable_switch_id); ofc_state.capable_switch_id = NULL; } } else { // todo anything else? nc_verb_verbose("%s: unsupported operation %u\n", __PRETTY_FUNCTION__, op); assert(0); return EXIT_FAILURE; } return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_xdpd_mgmt_cross_connections_xdpd_mgmt_cross_connection (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); print_element_names(node, 0); uint64_t dpid_1 = 0; uint64_t dpid_2 = 0; uint64_t port_no1 = 0; uint64_t port_no2 = 0; if (XMLDIFF_ADD & op) { int i=0; xmlNodePtr lsi; for (lsi = node->children->next; NULL != lsi; lsi = lsi->next, ++i) { assert(xmlStrEqual(lsi->name, BAD_CAST "switch")); // resolve dpid char buf[255]; xmlStrPrintf(buf, sizeof(buf), "/ofc:capable-switch/ofc:logical-switches/ofc:switch[ofc:id='%s']", XML_GET_CONTENT(lsi->children->children)); xmlXPathObjectPtr xpath_obj_ptr = get_node(lsi->doc, namespace_mapping, buf); assert(xpath_obj_ptr); assert(xpath_obj_ptr->nodesetval); // there can only be one lsi with this id if (1 == xpath_obj_ptr->nodesetval->nodeNr) { xmlNodePtr dpid_node = find_element(BAD_CAST "datapath-id", xpath_obj_ptr->nodesetval->nodeTab[0]->children); assert(dpid_node); if (0 == i) { dpid_1 = parse_dpid(XML_GET_CONTENT(dpid_node->children)); } else { dpid_2 = parse_dpid(XML_GET_CONTENT(dpid_node->children)); } } else { // otherwise something is really screwed assert(0); } xmlXPathFreeObject(xpath_obj_ptr); xmlNodePtr requested_portnum = find_element(BAD_CAST "requested-of-port-number", lsi->children); if (NULL != requested_portnum) { if (0 == i) { port_no1 = strtoul(XML_GET_CONTENT(requested_portnum->children), NULL, 10); } else { port_no2 = strtoul(XML_GET_CONTENT(requested_portnum->children), NULL, 10); } } } nc_verb_verbose("dpid_1 = %lx, dpid_2 = %lx\n", dpid_1, dpid_2); lsi_cross_connect(ofc_state.xmp_client_handle, dpid_1, port_no1, dpid_2, port_no2); } return EXIT_SUCCESS; }
int ofcds_init(void *UNUSED(data)) { if (!ovsdb_path) { /* default path */ asprintf(&ovsdb_path, "unix:%s/db.sock", ovs_rundir()); } if (ofc_init(ovsdb_path) == false) { return EXIT_FAILURE; } /* hack - OVS calls openlog() and rewrites the syslog settings of the * ofc-server. So we have to rewrite syslog settings back by another * openlog() call */ if (ofc_daemonize) { openlog("ofc-server", LOG_PID, LOG_DAEMON); } else { openlog("ofc-server", LOG_PID | LOG_PERROR, LOG_DAEMON); } /* get startup data */ gds_startup = xmlReadFile(OFC_DATADIR "/startup.xml", NULL, XML_READ_OPT); /* check that there are some data, if not, continue with empty startup */ if (!xmlDocGetRootElement(gds_startup)) { xmlFreeDoc(gds_startup); gds_startup = NULL; } nc_verb_verbose("OF-CONFIG datastore initialized."); return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_logical_switches (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); print_element_names(node, 0); int rv = EXIT_SUCCESS; if (NULL != node->children) { assert(ofc_state.lsi_list); assert(XMLDIFF_CHAIN & op); if ((XMLDIFF_ADD|XMLDIFF_REM|XMLDIFF_MOD|XMLDIFF_CHAIN) & op) { struct lsi *current_lsi; while ( (current_lsi = list_next(ofc_state.lsi_list)) ) { handle_ports(current_lsi->res.port_list_del); } while ( (current_lsi = list_pop_head(ofc_state.lsi_list)) ) { handle_ports(current_lsi->res.port_list_add); lsi_cleanup(current_lsi); } } else { nc_verb_error("unsupported op"); assert(0); } list_delete(ofc_state.lsi_list); ofc_state.lsi_list = NULL; } return rv; }
/* Signal handler - controls main loop */ void signal_handler(int sig) { nc_verb_verbose("Signal %d received.", sig); switch (sig) { case SIGINT: case SIGTERM: case SIGQUIT: case SIGABRT: case SIGKILL: if (mainloop == 0) { /* first attempt */ mainloop = 1; } else { /* second attempt */ nc_verb_error("Hey! I need some time, be patient next time!"); exit(EXIT_FAILURE); } break; default: nc_verb_error("Exiting on signal: %d", sig); exit(EXIT_FAILURE); break; } }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers_ofc_controller (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); print_element_names(node, 0); if (NULL == *data) { *data = calloc(1, sizeof(struct lsi)); assert(*data); } if ((XMLDIFF_ADD) & op) { if (NULL == LSI(data)->controller_list_add) { LSI(data)->controller_list_add = list_new(); assert(LSI(data)->controller_list_add); } list_append_data(LSI(data)->controller_list_add, __data); __data = NULL; } else if ((XMLDIFF_REM) & op) { if (NULL == LSI(data)->controller_list_del) { LSI(data)->controller_list_del = list_new(); assert(LSI(data)->controller_list_del); } list_append_data(LSI(data)->controller_list_del, __data); __data = NULL; } else { nc_verb_error("not implemented"); assert(0); } return EXIT_SUCCESS; }
/** * @brief Free all resources allocated on plugin runtime and prepare plugin for removal. */ void netopeer_transapi_close_tls(void) { struct np_trusted_cert* cert, *del_cert; struct np_ctn_item* item, *del_item; nc_verb_verbose("Netopeer TLS cleanup."); free(netopeer_options.tls_opts->server_cert); free(netopeer_options.tls_opts->server_key); for (cert = netopeer_options.tls_opts->trusted_certs; cert != NULL;) { del_cert = cert; cert = cert->next; free(del_cert->cert); free(del_cert); } free(netopeer_options.tls_opts->crl_dir); for (item = netopeer_options.tls_opts->ctn_map; item != NULL;) { del_item = item; item = item->next; free(del_item->fingerprint); free(del_item->name); free(del_item); } pthread_mutex_destroy(&netopeer_options.tls_opts->tls_ctx_lock); pthread_mutex_destroy(&netopeer_options.tls_opts->crl_dir_lock); pthread_mutex_destroy(&netopeer_options.tls_opts->ctn_map_lock); free(netopeer_options.tls_opts); netopeer_options.tls_opts = NULL; }
static void handle_ports(void *list) { if (NULL != list) { // handle ports struct port *p; while ((p = list_pop_head(list))) { nc_verb_verbose("dpid=%lx port %s with op=%u\n", p->dpid, p->resource_id, p->op); if (ADD == p->op) { // attach port port_attach(ofc_state.xmp_client_handle, p->dpid, p->resource_id); } else if (DELETE == p->op) { // detach port port_detach(ofc_state.xmp_client_handle, p->dpid, p->resource_id); } else { assert(0); } xmlFree(p->resource_id); free(p); } } }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_resources_ofc_port_ofc_configuration_ofc_admin_state (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); print_element_names(node, 0); int rv = EXIT_SUCCESS; int down = 0; // default is up if ((XMLDIFF_ADD|XMLDIFF_MOD) & op) { if (xmlStrEqual(XML_GET_CONTENT(node->children), BAD_CAST "down")) { down = 1; } // sanity check... if the content is not "down", it has to be "up" assert(down || xmlStrEqual(XML_GET_CONTENT(node->children), BAD_CAST "up")); // currently the resource-id is the port name (even if the name is not set xmlNodePtr tmp = find_element(BAD_CAST "resource-id", node->parent->parent->children); assert(tmp); if (down) { // set interface down nc_verb_verbose("set interface %s down\n", tmp->children->content); if (port_disable(ofc_state.xmp_client_handle, tmp->children->content)) { rv = EXIT_FAILURE; } } else { // set interface up nc_verb_verbose("set interface %s up\n", tmp->children->content); if (port_enable(ofc_state.xmp_client_handle, tmp->children->content)) { rv = EXIT_FAILURE; } } } else if (XMLDIFF_REM & op) { // setting interface up } else { nc_verb_error("unsupported op"); assert(0); } return rv; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); xmlSaveFormatFileEnc("-", node->doc, "UTF-8", 1); return EXIT_SUCCESS; }
/** * @brief Initialize plugin after loaded and before any other functions are called. * This function should not apply any configuration data to the controlled device. If no * running is returned (it stays *NULL), complete startup configuration is consequently * applied via module callbacks. When a running configuration is returned, libnetconf * then applies (via module's callbacks) only the startup configuration data that * differ from the returned running configuration data. * Please note, that copying startup data to the running is performed only after the * libnetconf's system-wide close - see nc_close() function documentation for more * information. * @param[out] running Current configuration of managed device. * @return EXIT_SUCCESS or EXIT_FAILURE */ int transapi_init(xmlDocPtr * running) { assert(running); assert(NULL == *running); memset(&ofc_state, 0, sizeof(struct of_config__status)); ofc_state.xmp_client_handle = new_xmp_client(); // since we currently cannot query the switch_id we set it manually ofc_state.capable_switch_id = strdup("xdpd-switch"); // create running config as following: // +--rw capable-switch // +--rw id inet:uri // +--rw configuration-points // +--rw resources // +--rw logical-switches nc_verb_verbose("create running config"); *running = xmlNewDoc(BAD_CAST "1.0"); assert(*running); xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "capable-switch"); assert(root); xmlDocSetRootElement(*running, root); xmlNsPtr ns = xmlNewNs(root, BAD_CAST namespace_mapping[0].href, NULL); assert(ns); xmlSetNs(root, ns); xmlNodePtr id = xmlNewChild(root, ns, BAD_CAST "id", BAD_CAST ofc_state.capable_switch_id); assert(id); xmlNodePtr config_points = xmlNewChild(root, ns, BAD_CAST "configuration-points", NULL); assert(config_points); xmlNodePtr resources = xmlNewChild(root, ns, BAD_CAST "resources", NULL); assert(resources); get_resources(ofc_state.xmp_client_handle, resources); xmlNodePtr lsis = xmlNewChild(root, ns, BAD_CAST "logical-switches", NULL); assert(lsis); get_lsi_config(ofc_state.xmp_client_handle, lsis); xmlSaveFormatFileEnc("-", *running, "UTF-8", 1); nc_verb_verbose("init done\n"); return EXIT_SUCCESS; }
int netopeer_transapi_init_tls(void) { /* there is no default configuration, but what the heck */ nc_verb_verbose("Setting the default configuration for the cfgnetopeer module TLS..."); netopeer_options.tls_opts = calloc(1, sizeof(struct np_options_tls)); pthread_mutex_init(&netopeer_options.tls_opts->tls_ctx_lock, NULL); pthread_mutex_init(&netopeer_options.tls_opts->crl_dir_lock, NULL); pthread_mutex_init(&netopeer_options.tls_opts->ctn_map_lock, NULL); return EXIT_SUCCESS; }
/** * @brief Free all resources allocated on plugin runtime and prepare plugin for removal. */ void transapi_close(void) { delete_xmp_client(ofc_state.xmp_client_handle); ofc_state.xmp_client_handle = NULL; if(ofc_state.capable_switch_id) { free(ofc_state.capable_switch_id); ofc_state.capable_switch_id = NULL; } nc_verb_verbose("closed\n"); return; }
int ofcds_unlock(void *UNUSED(data), NC_DATASTORE target, const char *session_id, struct nc_err **error) { int *locked; char **sid; switch (target) { case NC_DATASTORE_RUNNING: locked = &(locks.running); sid = &(locks.running_sid); break; case NC_DATASTORE_STARTUP: locked = &(locks.startup); sid = &(locks.startup_sid); break; case NC_DATASTORE_CANDIDATE: locked = &(locks.cand); sid = &(locks.cand_sid); break; default: /* handled by libnetconf */ return EXIT_FAILURE; } if (*locked) { if (strcmp(*sid, session_id) == 0) { /* correct request, unlock */ *locked = 0; free(*sid); *sid = NULL; nc_verb_verbose("OFC datastore %d unlocked by %s.", target, session_id); } else { /* locked by another session */ *error = nc_err_new(NC_ERR_LOCK_DENIED); nc_err_set(*error, NC_ERR_PARAM_INFO_SID, *sid); nc_err_set(*error, NC_ERR_PARAM_MSG, "Target datastore is locked by another session."); return EXIT_FAILURE; } } else { /* not locked */ *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Target datastore is not locked."); return EXIT_FAILURE; } return EXIT_SUCCESS; }
/** * @brief Free all resources allocated on plugin runtime and prepare plugin for removal. */ void netopeer_transapi_close(void) { #ifdef NP_TLS if (ncds_feature_isenabled("cfgnetopeer", "tls")) { netopeer_transapi_close_tls(); } #endif #ifdef NP_SSH if (ncds_feature_isenabled("cfgnetopeer", "ssh")) { netopeer_transapi_close_ssh(); } #endif nc_verb_verbose("Netopeer cleanup."); while (netopeer_options.modules) { module_disable(netopeer_options.modules, 1); } }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers_ofc_controller_ofc_ip_address (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); assert(__data); if ((XMLDIFF_ADD) & op) { // fixme handle zone in address (see http://www.netconfcentral.org/modules/ietf-inet-types) CONTROLLER(__data)->ip_domain = parse_ip_address(XML_GET_CONTENT(node->children), &CONTROLLER(__data)->ip); } else if ((XMLDIFF_REM) & op) { } else { nc_verb_error("not implemented"); assert(0); } return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers_ofc_controller_ofc_port (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); assert(__data); if ((XMLDIFF_ADD) & op) { CONTROLLER(__data)->port = strtoul(XML_GET_CONTENT(node->children), NULL, 10); } else if ((XMLDIFF_REM) & op) { } else { nc_verb_error("not implemented"); assert(0); } return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers_ofc_controller_ofc_id (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); assert(NULL == __data); if ((XMLDIFF_ADD|XMLDIFF_REM) & op) { __data = calloc(1, sizeof(struct controller)); CONTROLLER(__data)->id = strdup(XML_GET_CONTENT(node->children)); assert(CONTROLLER(__data)->id); } else { nc_verb_error("not implemented"); assert(0); } return EXIT_SUCCESS; }
/** * @brief Free all resources allocated on plugin runtime and prepare plugin for removal. */ void netopeer_transapi_close_ssh(void) { struct np_auth_key* key, *del_key; nc_verb_verbose("Netopeer SSH cleanup."); free(netopeer_options.ssh_opts->rsa_key); free(netopeer_options.ssh_opts->dsa_key); for (key = netopeer_options.ssh_opts->client_auth_keys; key != NULL;) { del_key = key; key = key->next; free(del_key->path); free(del_key->username); free(del_key); } pthread_mutex_destroy(&netopeer_options.ssh_opts->client_keys_lock); free(netopeer_options.ssh_opts); netopeer_options.ssh_opts = NULL; }
int ofcds_lock(void *UNUSED(data), NC_DATASTORE target, const char *session_id, struct nc_err **error) { int *locked; char **sid; switch (target) { case NC_DATASTORE_RUNNING: locked = &(locks.running); sid = &(locks.running_sid); break; case NC_DATASTORE_STARTUP: locked = &(locks.startup); sid = &(locks.startup_sid); break; case NC_DATASTORE_CANDIDATE: locked = &(locks.cand); sid = &(locks.cand_sid); break; default: /* handled by libnetconf */ return EXIT_FAILURE; } if (*locked) { /* datastore is already locked */ *error = nc_err_new(NC_ERR_LOCK_DENIED); nc_err_set(*error, NC_ERR_PARAM_INFO_SID, *sid); return EXIT_FAILURE; } else { /* remember the lock */ *locked = 1; *sid = strdup(session_id); nc_verb_verbose("OFC datastore %d locked by %s.", target, session_id); } return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_datapath_id (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); assert(NULL == __data); if (NULL == *data) { *data = calloc(1, sizeof(struct lsi)); assert(*data); } if ((XMLDIFF_ADD|XMLDIFF_REM) & op) { xmlChar* text = xmlNodeListGetString(node->doc, node->children, 1); uint64_t dpid = parse_dpid(text); xmlFree(text); LSI(data)->dpid = dpid; } else { // todo add operation to modify dpid nc_verb_error("not implemented"); assert(0); } return EXIT_SUCCESS; }
/** * @brief Retrieve state data from device and return them as XML document * * @param model Device data model. libxml2 xmlDocPtr. * @param running Running datastore content. libxml2 xmlDocPtr. * @param[out] err Double pointer to error structure. Fill error when some occurs. * @return State data as libxml2 xmlDocPtr or NULL in case of error. */ xmlDocPtr get_state_data (xmlDocPtr model, xmlDocPtr running, struct nc_err **err) { nc_verb_verbose("get_state_data\n"); nc_verb_verbose("erropt=%u\n", erropt); xmlDocPtr state; xmlNodePtr root; xmlNsPtr ns; state = xmlNewDoc(BAD_CAST "1.0"); root = xmlNewDocNode(state, NULL, BAD_CAST "capable-switch", NULL); xmlDocSetRootElement(state, root); ns = xmlNewNs(root, BAD_CAST "urn:onf:of111:config:yang", NULL); xmlSetNs(root, ns); // state that should be queried here // ### base // #/ofc:capable-switch/ofc:config-version xmlNewChild(root, ns, BAD_CAST "config-version", BAD_CAST "1.1.1"); // // ### configuration points // // ### Resources // xmlNodePtr resources = xmlNewChild(root, NULL, BAD_CAST "resources", NULL); // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:number // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:current-rate // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:max-rate // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:state // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:state/ofc:oper-state // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:state/ofc:blocked // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:state/ofc:live // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current/ofc:rate // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current/ofc:auto-negotiate // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current/ofc:medium // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:current/ofc:pause // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported/ofc:rate // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported/ofc:auto-negotiate // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported/ofc:medium // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:supported/ofc:pause // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer/ofc:rate // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer/ofc:auto-negotiate // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer/ofc:medium // #/ofc:capable-switch/ofc:resources/ofc:port/ofc:features/ofc:advertised-peer/ofc:pause get_port_info(ofc_state.xmp_client_handle, resources, running); xmlNodePtr lsis = xmlNewChild(root, NULL, BAD_CAST "logical-switches", NULL); // ### LSIs // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:max-buffered-packets // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:max-tables // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:max-ports // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:flow-statistics // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:table-statistics // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:port-statistics // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-statistics // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:queue-statistics // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:reassemble-ip-fragments // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:block-looping-ports // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:reserved-port-types // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:reserved-port-types/ofc:type // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-types // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-types/ofc:type // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-capabilities // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:group-capabilities/ofc:capability // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:action-types // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:action-types/ofc:type // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:instruction-types // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:capabilities/ofc:instruction-types/ofc:type // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:connection-state // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:current-version // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:supported-versions // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:local-ip-address-in-use // #/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:controllers/ofc:controller/ofc:state/ofc:local-port-in-use get_lsi_info(ofc_state.xmp_client_handle, lsis, running); return state; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_resources_ofc_port (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); print_element_names(node, 0); // retrieve the dpid of this twig xmlNodePtr tmp = find_element(BAD_CAST "datapath-id", node->parent->parent->children); assert(tmp); uint64_t dpid = parse_dpid(tmp->children->content); int rv = EXIT_SUCCESS; // fixme depending on the erropt (e.g. NC_EDIT_ERROPT_ROLLBACK we might still have *data set) assert(data); if (NULL == *data) { *data = calloc(1, sizeof(struct lsi)); assert(*data); } if (XMLDIFF_ADD & op) { xmlChar buf[255]; // check if port is already attached xmlStrPrintf(buf, sizeof(buf), "/ofc:capable-switch/ofc:logical-switches/ofc:switch/ofc:resources/ofc:port[text()='%s']", XML_GET_CONTENT(node->children)); xmlXPathObjectPtr xpath_obj_ptr = get_node(node->doc, namespace_mapping, buf); assert(xpath_obj_ptr); assert(xpath_obj_ptr->nodesetval); if (1 == xpath_obj_ptr->nodesetval->nodeNr) { if (NULL == LSI(data)->res.port_list_add) { LSI(data)->res.port_list_add = list_new(); assert(((struct lsi* )*data)->res.port_list_add); } struct port *p = calloc(1, sizeof(struct port)); p->resource_id = xmlNodeListGetString(node->doc, node->children, 1); p->op = ADD; p->dpid = dpid; list_append_data(LSI(data)->res.port_list_add, p); nc_verb_verbose("added to list: dpid=%lx port %s with op=%u\n", p->dpid, p->resource_id, p->op); } else { // nodeNr > 1 ==> already attached port nc_verb_verbose("attachment failed dpid=%lx port %s: port already attached.\n", dpid, XML_GET_CONTENT(node->children)); rv = EXIT_FAILURE; } xmlXPathFreeObject(xpath_obj_ptr); } else if (XMLDIFF_REM & op) { if (NULL == LSI(data)->res.port_list_del) { LSI(data)->res.port_list_del = list_new(); assert(((struct lsi* ) *data)->res.port_list_del); } struct port *p = calloc(1, sizeof(struct port)); p->resource_id = xmlNodeListGetString(node->doc, node->children, 1); p->op = DELETE; p->dpid = dpid; list_append_data(LSI(data)->res.port_list_del, p); nc_verb_verbose("added to list: dpid=%lx port %s with op=%u\n", p->dpid, p->resource_id, p->op); } else { // todo implement nc_verb_error("not implemented"); assert(0); } return rv; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_resources_ofc_port_ofc_features (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); print_element_names(node, 0); return EXIT_SUCCESS; }
int cmd_feature(const char* arg) { char* argv, *ptr, *state_str, *saveptr; int i, ret = 0; struct model_list* list; struct data_model* model; if (strlen(arg) < 8) { cmd_feature_help(); return 1; } argv = strdupa(arg + strlen("feature ")); ptr = strtok_r(argv, " ", &saveptr); if (ptr == NULL) { cmd_feature_help(); return 1; } list = find_model(ptr); if (list == NULL) { nc_verb_error("No model \"%s\" found", ptr); return 1; } model = list->model; ptr = strtok_r(NULL, " ", &saveptr); /* we are done, no more arguments */ if (ptr == NULL) { printf("Features:\n"); if (model->features == NULL) { printf("\tnone\n"); return 0; } for (i = 0; model->features[i] != NULL; ++i) { printf("\t%s %s\n", model->features[i]->name, (model->features[i]->enabled ? "ON" : "OFF")); } return 0; } do { state_str = strtok_r(NULL, " ", &saveptr); } while (state_str != NULL && strcmp(state_str, "on") != 0 && strcmp(state_str, "off") != 0); /* there was no "yes" or "no" at the end */ if (state_str == NULL) { cmd_feature_help(); return 1; } if (model->features == NULL) { nc_verb_error("Model does not have any features"); return 1; } /* all features */ if (strcmp(ptr, "*") == 0) { for (i = 0; model->features[i] != NULL; ++i) { if (strcmp(state_str, "on") == 0) { model->features[i]->enabled = 1; } else { model->features[i]->enabled = 0; } } } else { /* one or more features */ ptr = argv + strlen(argv)+1; while (ptr != state_str) { for (i = 0; model->features[i] != NULL; ++i) { if (strcmp(model->features[i]->name, ptr) == 0) { if ((model->features[i]->enabled && strcmp(state_str, "on") == 0) || (!model->features[i]->enabled && strcmp(state_str, "off") == 0)) { nc_verb_verbose("Feature \"%s\" is already %s", ptr, state_str); } else if (strcmp(state_str, "on") == 0) { model->features[i]->enabled = 1; } else { model->features[i]->enabled = 0; } break; } } if (model->features[i] == NULL) { nc_verb_error("Model does not have the feature \"%s\"", ptr); ret = 1; } ptr = ptr + strlen(ptr)+1; } } return ret; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch_ofc_controllers (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); nc_verb_verbose("currently ignored"); return EXIT_SUCCESS; }
int netopeer_transapi_init_ssh(void) { xmlDocPtr doc; struct nc_err* error = NULL; const char* str_err; nc_verb_verbose("Setting the default configuration for the cfgnetopeer module SSH..."); netopeer_options.ssh_opts = calloc(1, sizeof(struct np_options_ssh)); pthread_mutex_init(&netopeer_options.ssh_opts->client_keys_lock, NULL); doc = xmlReadDoc(BAD_CAST "<netopeer xmlns=\"urn:cesnet:tmc:netopeer:1.0\"><ssh><server-keys><rsa-key>/etc/ssh/ssh_host_rsa_key</rsa-key></server-keys><password-auth-enabled>true</password-auth-enabled><auth-attempts>3</auth-attempts><auth-timeout>10</auth-timeout></ssh></netopeer>", NULL, NULL, 0); if (doc == NULL) { nc_verb_error("Unable to parse the default cfgnetopeer SSH configuration."); return EXIT_FAILURE; } if (callback_n_netopeer_n_ssh_n_server_keys_n_rsa_key(NULL, XMLDIFF_ADD, NULL, doc->children->children->children->children, &error) != EXIT_SUCCESS) { if (error != NULL) { str_err = nc_err_get(error, NC_ERR_PARAM_MSG); if (str_err != NULL) { nc_verb_error(str_err); } nc_err_free(error); } xmlFreeDoc(doc); return EXIT_FAILURE; } if (callback_n_netopeer_n_ssh_n_password_auth_enabled(NULL, XMLDIFF_ADD, NULL, doc->children->children->children->next, &error) != EXIT_SUCCESS) { if (error != NULL) { str_err = nc_err_get(error, NC_ERR_PARAM_MSG); if (str_err != NULL) { nc_verb_error(str_err); } nc_err_free(error); } xmlFreeDoc(doc); return EXIT_FAILURE; } if (callback_n_netopeer_n_ssh_n_auth_attempts(NULL, XMLDIFF_ADD, NULL, doc->children->children->children->next->next, &error) != EXIT_SUCCESS) { if (error != NULL) { str_err = nc_err_get(error, NC_ERR_PARAM_MSG); if (str_err != NULL) { nc_verb_error(str_err); } nc_err_free(error); } xmlFreeDoc(doc); return EXIT_FAILURE; } if (callback_n_netopeer_n_ssh_n_auth_timeout(NULL, XMLDIFF_ADD, NULL, doc->children->children->children->next->next->next, &error) != EXIT_SUCCESS) { if (error != NULL) { str_err = nc_err_get(error, NC_ERR_PARAM_MSG); if (str_err != NULL) { nc_verb_error(str_err); } nc_err_free(error); } xmlFreeDoc(doc); return EXIT_FAILURE; } xmlFreeDoc(doc); return EXIT_SUCCESS; }
void listen_loop(int do_init) { struct client_struct* new_client; struct np_sock npsock = {.count = 0}; int ret; struct timespec ts; #ifdef NP_SSH ssh_bind sshbind = NULL; #endif #ifdef NP_TLS SSL_CTX* tlsctx = NULL; #endif /* Init */ if (do_init) { #ifdef NP_SSH np_ssh_init(); #endif #ifdef NP_TLS np_tls_init(); #endif if ((ret = pthread_create(&netopeer_state.data_tid, NULL, data_thread, NULL)) != 0) { nc_verb_error("%s: failed to create a thread (%s)", __func__, strerror(ret)); return; } if ((ret = pthread_create(&netopeer_state.netconf_rpc_tid, NULL, netconf_rpc_thread, NULL)) != 0) { nc_verb_error("%s: failed to create a thread (%s)", __func__, strerror(ret)); return; } } /* Main accept loop */ do { new_client = NULL; /* Binds change check */ if (netopeer_options.binds_change_flag) { /* BINDS LOCK */ pthread_mutex_lock(&netopeer_options.binds_lock); sock_cleanup(&npsock); sock_listen(netopeer_options.binds, &npsock); netopeer_options.binds_change_flag = 0; /* BINDS UNLOCK */ pthread_mutex_unlock(&netopeer_options.binds_lock); if (npsock.count == 0) { nc_verb_warning("Server is not listening on any address!"); } } #ifdef NP_SSH sshbind = np_ssh_server_id_check(sshbind); #endif #ifdef NP_TLS tlsctx = np_tls_server_id_check(tlsctx); #endif #ifndef DISABLE_CALLHOME /* Callhome client check */ if (callhome_client != NULL) { /* CALLHOME LOCK */ pthread_mutex_lock(&callhome_lock); new_client = callhome_client; callhome_client = NULL; /* CALLHOME UNLOCK */ pthread_mutex_unlock(&callhome_lock); } #endif /* Listen client check */ if (new_client == NULL) { new_client = sock_accept(&npsock); } /* New client full structure creation */ if (new_client != NULL) { /* Maximum number of sessions check */ if (netopeer_options.max_sessions > 0) { ret = 0; #ifdef NP_SSH ret += np_ssh_session_count(); #endif #ifdef NP_TLS ret += np_tls_session_count(); #endif if (ret >= netopeer_options.max_sessions) { nc_verb_error("Maximum number of sessions reached, droppping the new client."); new_client->to_free = 1; switch (new_client->transport) { #ifdef NP_SSH case NC_TRANSPORT_SSH: client_free_ssh((struct client_struct_ssh*)new_client); break; #endif #ifdef NP_TLS case NC_TRANSPORT_TLS: client_free_tls((struct client_struct_tls*)new_client); break; #endif default: nc_verb_error("%s: internal error (%s:%d)", __func__, __FILE__, __LINE__); } free(new_client); /* sleep to prevent clients from immediate connection retry */ usleep(netopeer_options.response_time*1000); continue; } } switch (new_client->transport) { #ifdef NP_SSH case NC_TRANSPORT_SSH: ret = np_ssh_create_client((struct client_struct_ssh*)new_client, sshbind); if (ret != 0) { new_client->to_free = 1; client_free_ssh((struct client_struct_ssh*)new_client); } break; #endif #ifdef NP_TLS case NC_TRANSPORT_TLS: ret = np_tls_create_client((struct client_struct_tls*)new_client, tlsctx); if (ret != 0) { new_client->to_free = 1; client_free_tls((struct client_struct_tls*)new_client); } break; #endif default: nc_verb_error("Client with an unknown transport protocol, dropping it."); new_client->to_free = 1; ret = 1; } /* client is not valid, some error occured */ if (ret != 0) { free(new_client); continue; } /* add the client into the global clients structure */ /* GLOBAL WRITE LOCK */ pthread_rwlock_wrlock(&netopeer_state.global_lock); client_append(&netopeer_state.clients, new_client); /* GLOBAL WRITE UNLOCK */ pthread_rwlock_unlock(&netopeer_state.global_lock); } } while (!quit && !restart_soft); /* Cleanup */ sock_cleanup(&npsock); #ifdef NP_SSH ssh_bind_free(sshbind); #endif #ifdef NP_TLS SSL_CTX_free(tlsctx); #endif if (!restart_soft) { if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { nc_verb_warning("%s: failed to get time (%s)", strerror(errno)); } ts.tv_sec += THREAD_JOIN_QUIT_TIMEOUT; /* wait for all the clients to exit nicely themselves */ if ((ret = pthread_timedjoin_np(netopeer_state.netconf_rpc_tid, NULL, &ts)) != 0) { nc_verb_warning("%s: failed to join the netconf RPC thread (%s)", __func__, strerror(ret)); if (ret == ETIMEDOUT) { pthread_cancel(netopeer_state.netconf_rpc_tid); } } if ((ret = pthread_timedjoin_np(netopeer_state.data_tid, NULL, &ts)) != 0) { nc_verb_warning("%s: failed to join the SSH data thread (%s)", __func__, strerror(ret)); if (ret == ETIMEDOUT) { pthread_cancel(netopeer_state.data_tid); } } #ifdef NP_SSH np_ssh_cleanup(); #endif #ifdef NP_TLS np_tls_cleanup(); #endif } } int main(int argc, char** argv) { struct sigaction action; sigset_t block_mask; char *aux_string = NULL, path[PATH_MAX]; int next_option; int daemonize = 0, len; int listen_init = 1; struct np_module* netopeer_module = NULL, *server_module = NULL; /* initialize message system and set verbose and debug variables */ if ((aux_string = getenv(ENVIRONMENT_VERBOSE)) == NULL) { netopeer_options.verbose = NC_VERB_ERROR; } else { netopeer_options.verbose = atoi(aux_string); } aux_string = NULL; /* for sure to avoid unwanted changes in environment */ /* parse given options */ while ((next_option = getopt(argc, argv, OPTSTRING)) != -1) { switch (next_option) { case 'd': daemonize = 1; break; case 'h': print_usage(argv[0]); break; case 'v': netopeer_options.verbose = atoi(optarg); break; case 'V': print_version(argv[0]); break; default: print_usage(argv[0]); break; } } /* set signal handler */ sigfillset (&block_mask); action.sa_handler = signal_handler; action.sa_mask = block_mask; action.sa_flags = 0; sigaction(SIGINT, &action, NULL); sigaction(SIGQUIT, &action, NULL); sigaction(SIGABRT, &action, NULL); sigaction(SIGTERM, &action, NULL); sigaction(SIGHUP, &action, NULL); nc_callback_print(clb_print); /* normalize value if not from the enum */ if (netopeer_options.verbose > NC_VERB_DEBUG) { netopeer_options.verbose = NC_VERB_DEBUG; } nc_verbosity(netopeer_options.verbose); /* go to the background as a daemon */ if (daemonize == 1) { if (daemon(0, 0) != 0) { nc_verb_error("Going to background failed (%s)", strerror(errno)); return EXIT_FAILURE; } openlog("netopeer-server", LOG_PID, LOG_DAEMON); } else { openlog("netopeer-server", LOG_PID|LOG_PERROR, LOG_DAEMON); } /* make sure we were executed by root */ if (geteuid() != 0) { nc_verb_error("Failed to start, must have root privileges."); return EXIT_FAILURE; } /* * this initialize the library and check potential ABI mismatches * between the version it was compiled for and the actual shared * library used. */ LIBXML_TEST_VERSION /* initialize library including internal datastores and maybee something more */ if (nc_init(NC_INIT_ALL | NC_INIT_MULTILAYER) < 0) { nc_verb_error("Library initialization failed."); return EXIT_FAILURE; } server_start = 1; restart: /* start NETCONF server module */ if ((server_module = calloc(1, sizeof(struct np_module))) == NULL) { nc_verb_error("Creating necessary NETCONF server plugin failed!"); return EXIT_FAILURE; } server_module->name = strdup(NCSERVER_MODULE_NAME); if (module_enable(server_module, 0)) { nc_verb_error("Starting necessary NETCONF server plugin failed!"); free(server_module->name); free(server_module); return EXIT_FAILURE; } /* start netopeer device module - it will start all modules that are * in its configuration and in server configuration */ if ((netopeer_module = calloc(1, sizeof(struct np_module))) == NULL) { nc_verb_error("Creating necessary Netopeer plugin failed!"); module_disable(server_module, 1); return EXIT_FAILURE; } netopeer_module->name = strdup(NETOPEER_MODULE_NAME); if (module_enable(netopeer_module, 0)) { nc_verb_error("Starting necessary Netopeer plugin failed!"); module_disable(server_module, 1); free(netopeer_module->name); free(netopeer_module); return EXIT_FAILURE; } server_start = 0; nc_verb_verbose("Netopeer server successfully initialized."); listen_loop(listen_init); /* unload Netopeer module -> unload all modules */ module_disable(server_module, 1); module_disable(netopeer_module, 1); /* main cleanup */ if (!restart_soft) { /* close libnetconf only when shutting down or hard restarting the server */ nc_close(); } if (restart_soft) { nc_verb_verbose("Server is going to soft restart."); restart_soft = 0; listen_init = 0; goto restart; } else if (restart_hard) { nc_verb_verbose("Server is going to hard restart."); len = readlink("/proc/self/exe", path, PATH_MAX); path[len] = 0; xmlCleanupParser(); execv(path, argv); } /* *Free the global variables that may *have been allocated by the parser. */ xmlCleanupParser(); return EXIT_SUCCESS; }
int main (int argc, char** argv) { conn_t* conn = NULL; struct sigaction action; sigset_t block_mask; char *aux_string = NULL, path[PATH_MAX]; int next_option, ret; int daemonize = 0, len; int verbose = 0; struct module * netopeer_module = NULL, *server_module = NULL; /* initialize message system and set verbose and debug variables */ if ((aux_string = getenv (ENVIRONMENT_VERBOSE)) == NULL) { verbose = NC_VERB_ERROR; } else { verbose = atoi (aux_string); } aux_string = NULL; /* for sure to avoid unwanted changes in environment */ /* parse given options */ while ((next_option = getopt (argc, argv, OPTSTRING)) != -1) { switch (next_option) { case 'd': daemonize = 1; break; case 'h': print_usage (argv[0]); break; case 'v': verbose = atoi (optarg); break; case 'V': print_version (argv[0]); break; default: print_usage (argv[0]); break; } } /* set signal handler */ sigfillset (&block_mask); action.sa_handler = signal_handler; action.sa_mask = block_mask; action.sa_flags = 0; sigaction (SIGINT, &action, NULL); sigaction (SIGQUIT, &action, NULL); sigaction (SIGABRT, &action, NULL); sigaction (SIGTERM, &action, NULL); sigaction (SIGKILL, &action, NULL); sigaction (SIGHUP, &action, NULL); nc_callback_print (clb_print); /* normalize value if not from the enum */ if (verbose < NC_VERB_ERROR) { nc_verbosity (NC_VERB_ERROR); } else if (verbose > NC_VERB_DEBUG) { nc_verbosity (NC_VERB_DEBUG); } else { nc_verbosity (verbose); } /* go to the background as a daemon */ if (daemonize == 1) { if (daemon(0, 0) != 0) { nc_verb_error("Going to background failed (%s)", strerror(errno)); return (EXIT_FAILURE); } openlog("netopeer-server", LOG_PID, LOG_DAEMON); } else { openlog("netopeer-server", LOG_PID|LOG_PERROR, LOG_DAEMON); } /* make sure we were executed by root */ if (geteuid() != 0) { nc_verb_error("Failed to start, must have root privileges."); return (EXIT_FAILURE); } /* * this initialize the library and check potential ABI mismatches * between the version it was compiled for and the actual shared * library used. */ LIBXML_TEST_VERSION /* initialize library including internal datastores and maybee something more */ if ((ret = nc_init (NC_INIT_ALL | NC_INIT_MULTILAYER)) < 0) { nc_verb_error("Library initialization failed."); return (EXIT_FAILURE); } /* Initiate communication subsystem for communicate with agents */ conn = comm_init(ret & NC_INITRET_RECOVERY); if (conn == NULL) { nc_verb_error("Communication subsystem not initiated."); return (EXIT_FAILURE); } server_start = 1; restart: /* start NETCONF server module */ if ((server_module = calloc(1, sizeof(struct module))) == NULL) { nc_verb_error("Creating necessary NETCONF server plugin failed!"); comm_destroy(conn); return(EXIT_FAILURE); } server_module->name = strdup(NCSERVER_MODULE_NAME); if (module_enable(server_module, 0)) { nc_verb_error("Starting necessary NETCONF server plugin failed!"); free(server_module->name); free(server_module); comm_destroy(conn); return EXIT_FAILURE; } /* start netopeer device module - it will start all modules that are * in its configuration and in server configuration */ if ((netopeer_module = calloc(1, sizeof(struct module))) == NULL) { nc_verb_error("Creating necessary Netopeer plugin failed!"); module_disable(server_module, 1); comm_destroy(conn); return(EXIT_FAILURE); } netopeer_module->name = strdup(NETOPEER_MODULE_NAME); if (module_enable(netopeer_module, 0)) { nc_verb_error("Starting necessary Netopeer plugin failed!"); module_disable(server_module, 1); free(netopeer_module->name); free(netopeer_module); comm_destroy(conn); return EXIT_FAILURE; } server_start = 0; nc_verb_verbose("Netopeer server successfully initialized."); while (!done) { comm_loop(conn, 500); } /* unload Netopeer module -> unload all modules */ module_disable(server_module, 1); module_disable(netopeer_module, 1); /* main cleanup */ if (!restart_soft) { /* close connection and destroy all sessions only when shutting down or hard restarting the server */ comm_destroy(conn); server_sessions_destroy_all (); nc_close (); } /* *Free the global variables that may *have been allocated by the parser. */ xmlCleanupParser (); if (restart_soft) { nc_verb_verbose("Server is going to soft restart."); restart_soft = 0; done = 0; goto restart; } else if (restart_hard) { nc_verb_verbose("Server is going to hard restart."); len = readlink("/proc/self/exe", path, PATH_MAX); path[len] = 0; execv(path, argv); } return (EXIT_SUCCESS); }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_ofc_capable_switch_ofc_logical_switches_ofc_switch (void ** data, XMLDIFF_OP op, xmlNodePtr node, struct nc_err** error) { nc_verb_verbose("%s: data=%p, op=%d\n", __PRETTY_FUNCTION__, data, op); print_element_names(node, 0); if (NULL == ofc_state.lsi_list) { ofc_state.lsi_list = list_new(); assert(ofc_state.lsi_list); } assert(data); assert(*data); if (!(XMLDIFF_REM & op)) { list_append_data(ofc_state.lsi_list, *data); } int rv = EXIT_SUCCESS; if (XMLDIFF_ADD & op) { assert(XMLDIFF_CHAIN & op); nc_verb_verbose("create new lsi (dpid=%lu, name=%s)\n", LSI(data)->dpid, LSI(data)->dpname); if (lsi_create(ofc_state.xmp_client_handle, *data)) { rv = EXIT_FAILURE; } } else if (XMLDIFF_REM& op) { assert(XMLDIFF_CHAIN & op); nc_verb_verbose("destroy lsi (dpid=%lu, name=%s)\n", LSI(data)->dpid, LSI(data)->dpname); if ( lsi_destroy(ofc_state.xmp_client_handle, LSI(data)->dpid) ) { rv = EXIT_FAILURE; } // cannot have a port add during a lsi destroy assert(NULL == LSI(data)->res.port_list_add); // check if there were ports attached, then clean the list, because detachment takes place during lsi destruction if (NULL != LSI(data)->res.port_list_del) { struct port *p; while ((p = list_pop_head(LSI(data)->res.port_list_del))) { xmlFree(p->resource_id); free(p); } } // no need to deal with controllers seperately here lsi_cleanup(*data); } else if (XMLDIFF_MOD & op) { // direct sub elements changed nc_verb_error("not implemented XMLDIFF_MOD"); assert(0); } else if (XMLDIFF_CHAIN & op) { // resources or controllers changed (attachment of ports handled in parent) nc_verb_verbose("XMLDIFF_CHAIN\n"); // check dpid if (0 == LSI(data)->dpid) { xmlNodePtr tmp = find_element(BAD_CAST "datapath-id", node->children); assert(tmp); uint64_t dpid = parse_dpid(tmp->children->content); if (LSI(data)->dpid != dpid) { LSI(data)->dpid = dpid; } } if (LSI(data)->controller_list_add) { lsi_connect_to_controller(ofc_state.xmp_client_handle, LSI(data)); } if (LSI(data)->controller_list_del) { // fixme implement // assert(0); } } else { nc_verb_error("unsupported op"); assert(0); } *data = NULL; return rv; }