/* Causes 'r' to enter or leave fail-open mode, if appropriate. */ static void fail_open_periodic_cb(void *fail_open_) { struct fail_open_data *fail_open = fail_open_; int disconn_secs; bool open; if (time_now() < fail_open->boot_deadline) { return; } disconn_secs = rconn_failure_duration(fail_open->remote_rconn); open = disconn_secs >= fail_open->s->probe_interval * 3; if (open != (fail_open->lswitch != NULL)) { if (!open) { VLOG_WARN("No longer in fail-open mode"); lswitch_destroy(fail_open->lswitch); fail_open->lswitch = NULL; } else { VLOG_WARN("Could not connect to controller for %d seconds, " "failing open", disconn_secs); fail_open->lswitch = lswitch_create(fail_open->local_rconn, true, fail_open->s->max_idle); fail_open->last_disconn_secs = disconn_secs; } } else if (open && disconn_secs > fail_open->last_disconn_secs + 60) { VLOG_WARN("Still in fail-open mode after %d seconds disconnected " "from controller", disconn_secs); fail_open->last_disconn_secs = disconn_secs; } if (fail_open->lswitch) { lswitch_run(fail_open->lswitch, fail_open->local_rconn); } }
/* Check whether a fatal signal has occurred and, if so, call the fatal signal * hooks and exit. * * This function is called automatically by poll_block(), but specialized * programs that may not always call poll_block() on a regular basis should * also call it periodically. (Therefore, any function with "block" in its * name should call fatal_signal_run() each time it is called, either directly * or through poll_block(), because such functions can only used by specialized * programs that can afford to block outside their main loop around * poll_block().) */ void fatal_signal_run(void) { sig_atomic_t sig_nr; fatal_signal_init(); sig_nr = stored_sig_nr; if (sig_nr != SIG_ATOMIC_MAX) { char namebuf[SIGNAL_NAME_BUFSIZE]; ovs_mutex_lock(&mutex); #ifndef _WIN32 VLOG_WARN("terminating with signal %d (%s)", (int)sig_nr, signal_name(sig_nr, namebuf, sizeof namebuf)); #else VLOG_WARN("terminating with signal %d", (int)sig_nr); #endif call_hooks(sig_nr); fflush(stderr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); ovs_mutex_unlock(&mutex); OVS_NOT_REACHED(); } }
static void stream_read(struct stream *s) { if (s->fds[0] < 0) { return; } for (;;) { char buffer[512]; int error; size_t n; error = read_fully(s->fds[0], buffer, sizeof buffer, &n); ds_put_buffer(&s->log, buffer, n); if (error) { if (error == EAGAIN || error == EWOULDBLOCK) { return; } else { if (error != EOF) { VLOG_WARN("error reading subprocess pipe: %s", strerror(error)); } break; } } else if (s->log.length > PROCESS_MAX_CAPTURE) { VLOG_WARN("subprocess output overflowed %d-byte buffer", PROCESS_MAX_CAPTURE); break; } } close(s->fds[0]); s->fds[0] = -1; }
static uintptr_t get_max_stack(void) { static const char file_name[] = "/proc/self/maps"; char line[1024]; int line_number; FILE *f; f = fopen(file_name, "r"); if (f == NULL) { VLOG_WARN("opening %s failed: %s", file_name, strerror(errno)); return -1; } for (line_number = 1; fgets(line, sizeof line, f); line_number++) { if (strstr(line, "[stack]")) { uintptr_t end; if (sscanf(line, "%*x-%"SCNxPTR, &end) != 1) { VLOG_WARN("%s:%d: parse error", file_name, line_number); continue; } fclose(f); return end; } } fclose(f); VLOG_WARN("%s: no stack found", file_name); return -1; }
/* Connects to a Vlog server socket. 'path' may be: * * - A string that starts with a PID. If a non-null, non-absolute name * was passed to Vlog_server_socket::listen(), then it must follow the * PID in 'path'. * * - An absolute path (starting with '/') to a Vlog server socket or a * pidfile. If it is a pidfile, the pidfile will be read and translated * into a Vlog server socket file name. * * - A relative path, which is translated into a pidfile name and then * treated as above. * * Returns 0 if successful, otherwise a positive errno value. If successful, * sets '*clientp' to the new vlog_client, otherwise to NULL. */ int vlog_client_connect(const char *path, struct vlog_client **clientp) { static int counter; struct vlog_client *client; struct stat s; int error; client = xmalloc(sizeof *client); if (path[0] == '/') { client->connect_path = xstrdup(path); } else if (isdigit((unsigned char) path[0])) { client->connect_path = xasprintf("/tmp/vlogs.%s", path); } else { client->connect_path = make_pidfile_name(path); } client->bind_path = NULL; if (stat(client->connect_path, &s)) { error = errno; VLOG_WARN("could not stat \"%s\": %s", client->connect_path, strerror(error)); goto error; } else if (S_ISREG(s.st_mode)) { pid_t pid = read_pidfile(client->connect_path); if (pid < 0) { error = -pid; VLOG_WARN("could not read pidfile \"%s\": %s", client->connect_path, strerror(error)); goto error; } free(client->connect_path); client->connect_path = xasprintf("/tmp/vlogs.%ld", (long int) pid); } client->bind_path = xasprintf("/tmp/vlog.%ld.%d", (long int) getpid(), counter++); client->fd = make_unix_socket(SOCK_DGRAM, false, false, client->bind_path, client->connect_path); if (client->fd < 0) { error = -client->fd; goto error; } *clientp = client; return 0; error: free(client->connect_path); free(client->bind_path); free(client); *clientp = NULL; return error; }
/* Has the same effect as discover_numa_and_core(), but instead of reading * sysfs entries, extracts the info from 'dummy_config'. * * 'dummy_config' lists the numa_ids of each CPU separated by a comma, e.g. * - "0,0,0,0": four cores on numa socket 0. * - "0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1": 16 cores on two numa sockets. * - "0,0,0,0,1,1,1,1": 8 cores on two numa sockets. * * The different numa ids must be consecutives or the function will abort. */ static void discover_numa_and_core_dummy(const char *dummy_config) { char *conf = xstrdup(dummy_config); char *id, *saveptr = NULL; unsigned i = 0; long max_numa_id = 0; for (id = strtok_r(conf, ",", &saveptr); id; id = strtok_r(NULL, ",", &saveptr)) { struct hmap_node *hnode; struct numa_node *n; long numa_id; numa_id = strtol(id, NULL, 10); if (numa_id < 0 || numa_id >= MAX_NUMA_NODES) { VLOG_WARN("Invalid numa node %ld", numa_id); continue; } max_numa_id = MAX(max_numa_id, numa_id); hnode = hmap_first_with_hash(&all_numa_nodes, hash_int(numa_id, 0)); if (hnode) { n = CONTAINER_OF(hnode, struct numa_node, hmap_node); } else { n = insert_new_numa_node(numa_id); } insert_new_cpu_core(n, i); i++; }
/* Returns the current working directory as a malloc()'d string, or a null * pointer if the current working directory cannot be determined. */ char * get_cwd(void) { long int path_max; size_t size; /* Get maximum path length or at least a reasonable estimate. */ path_max = pathconf(".", _PC_PATH_MAX); size = (path_max < 0 ? 1024 : path_max > 10240 ? 10240 : path_max); /* Get current working directory. */ for (;;) { char *buf = xmalloc(size); if (getcwd(buf, size)) { return xrealloc(buf, strlen(buf) + 1); } else { int error = errno; free(buf); if (error != ERANGE) { VLOG_WARN("getcwd failed (%s)", strerror(error)); return NULL; } size *= 2; } } }
static void construct_dpdk_options(const struct smap *ovs_other_config, struct svec *args) { struct dpdk_options_map { const char *ovs_configuration; const char *dpdk_option; bool default_enabled; const char *default_value; } opts[] = { {"dpdk-lcore-mask", "-c", false, NULL}, {"dpdk-hugepage-dir", "--huge-dir", false, NULL}, {"dpdk-socket-limit", "--socket-limit", false, NULL}, }; int i; /*First, construct from the flat-options (non-mutex)*/ for (i = 0; i < ARRAY_SIZE(opts); ++i) { const char *value = smap_get(ovs_other_config, opts[i].ovs_configuration); if (!value && opts[i].default_enabled) { value = opts[i].default_value; } if (value) { if (!args_contains(args, opts[i].dpdk_option)) { svec_add(args, opts[i].dpdk_option); svec_add(args, value); } else { VLOG_WARN("Ignoring database defined option '%s' due to " "dpdk-extra config", opts[i].dpdk_option); } } } }
/* Tries to make 'sock' stop listening to 'multicast_group'. Returns 0 if * successful, otherwise a positive errno value. * * Multicast group numbers are always positive. * * It is not an error to attempt to leave a multicast group to which a socket * does not belong. * * On success, reading from 'sock' will still return any messages that were * received on 'multicast_group' before the group was left. */ int nl_sock_leave_mcgroup(struct nl_sock *sock, unsigned int multicast_group) { #ifdef _WIN32 struct ofpbuf msg_buf; struct message_multicast { struct nlmsghdr; /* if true, join; if else, leave*/ unsigned char join; }; struct message_multicast msg = { 0 }; nl_msg_put_nlmsghdr(&msg, sizeof(struct message_multicast), multicast_group, 0); msg.join = 0; msg_buf.base_ = &msg; msg_buf.data_ = &msg; msg_buf.size_ = msg.nlmsg_len; nl_sock_send__(sock, &msg_buf, msg.nlmsg_seq, 0); #else if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &multicast_group, sizeof multicast_group) < 0) { VLOG_WARN("could not leave multicast group %u (%s)", multicast_group, ovs_strerror(errno)); return errno; } #endif return 0; }
// Same as netdev_xxxx_set_config, to set lag param SMAP_FOR_EACH (node, args) { if (strcmp(node->key, "flow_ctl") == 0) { // lag port flow control mode, rx tx rx_tx } else if (strcmp(node->key, "lag_selected_min") == 0) { // minimum lag menber select number } else if (strcmp(node->key, "members") == 0) { // lag member } else if (strcmp(node->key, "lag_type") == 0) { // whether to use lacp } else if (strcmp(node->key, "lacp-system-id") == 0) { // system id } else if (!strcmp(node->key, "mtu")) { // lag mtu } else if (strcmp(node->key, "lacp-system-priority") == 0) { // lacp system priority } else if (strcmp(node->key, "lacp-time") == 0) { // fast lacp or slow lacp } else if (strcmp(node->key, "lacp-mode") == 0) { // active lacp or pasive lacp } else if (strcmp(node->key, "hash-mapping") == 0) { // } else if (strcmp(node->key, "loopback") == 0) { // whether could loopback } else { VLOG_WARN("Unsupported options:%s=%s for lag %s\n", node->key, node->value, dev_->name); } }
void handle_acl_log(const struct flow *headers, struct ofpbuf *userdata) { if (!VLOG_IS_INFO_ENABLED()) { return; } struct log_pin_header *lph = ofpbuf_try_pull(userdata, sizeof *lph); if (!lph) { VLOG_WARN("log data missing"); return; } size_t name_len = userdata->size; char *name = name_len ? xmemdup0(userdata->data, name_len) : NULL; struct ds ds = DS_EMPTY_INITIALIZER; ds_put_cstr(&ds, "name="); json_string_escape(name_len ? name : "<unnamed>", &ds); ds_put_format(&ds, ", verdict=%s, severity=%s: ", log_verdict_to_string(lph->verdict), log_severity_to_string(lph->severity)); flow_format(&ds, headers, NULL); VLOG_INFO("%s", ds_cstr(&ds)); ds_destroy(&ds); free(name); }
/*----------------------------------------------------------------------------- | Function: vtysh_ovsdb_config_logmsg | Responsibility : logs info/dbg/err/warn level message | Parameters: loglevel - logging level INFO/DBG/ERR/WARN | fmt - log message foramt | elipses - variable args | Return: void -----------------------------------------------------------------------------*/ void vtysh_ovsdb_config_logmsg(int loglevel, char *fmt, ...) { va_list args; va_start(args, fmt); switch (loglevel) { case VTYSH_OVSDB_CONFIG_ERR: VLOG_ERR(fmt, args); break; case VTYSH_OVSDB_CONFIG_WARN: VLOG_WARN(fmt, args); break; case VTYSH_OVSDB_CONFIG_INFO: VLOG_INFO(fmt, args); break; case VTYSH_OVSDB_CONFIG_DBG: VLOG_DBG(fmt, args); break; default : break; } va_end(args); }
// Add/delete lag member. static int xxxx_set_lag_members(struct netdev_xxxx_lag *lag, uint32_t *members, uint32_t members_count) { // remove old members from lag if (lag->members_count) { ports = xmalloc(lag->members_count * sizeof(ctype_usp_t)); for (i = 0; i < lag->members_count; i++) { // to remove a port from lag, first change port info of lag. set_phy_port_lag_info(lag->members[i], UINT32_MAX); // Then delete port from lag lacp group. lacp_delete_slave(lag->lacp, &lag->members[i]); } // Then delete port from lag group. lcmgr_delete_ports_from_lag(&lag_id, ports, lag->members_count); free(ports); } // add new members to lag if (members_count) { for (i = 0; i < members_count; i++) { // To add port to lag, first clear port vlan member. xxxx_clear_phy_port_vlan(members[i]); // Then set port tobe a lag. set_phy_port_lag_info(members[i], lag->port_no); // add port into lacp group. lacp_add_slave(lag->lacp, &members[i]); // If port is link up and use dynamic lacp: if (get_phy_port_link_up(members[i]) && get_phy_port_lacp_enable(members[i])) { // Then add port to lag group. ret = lcmgr_add_ports_to_lag(&lag_id, &port_usp, 1, OVS_USER); if (!ret) { VLOG_WARN("Failed to add port %d to ae%d.\n", members[i], lag_id.port); } // enable port STP. lcmgr_set_port_stp_state(&port_usp, CT_STP_STATE_FORWARDING); } // If port is link down, no need to add port into lag group. // If lag group of this port use static lacp, whether add port to lag is // determined by hardware. } } // reconfigure deleted physical ports for (i = 0; i < lag->members_count; i++) { if (phy_port_is_lag_member(lag->members[i])) { continue; } // Reset physical port vlan config, like pvid and vlan mode. xxxx_reset_phy_port_vlan(lag->members[i]); // For OVS, reset some files in netdev of this port. netdev_xxxx_reconfigure(lag->members[i]); } return 0; }
/* Breaks 'words' into words at white space, respecting shell-like quoting * conventions, and appends the words to 'svec'. */ void svec_parse_words(struct svec *svec, const char *words) { struct ds word = DS_EMPTY_INITIALIZER; const char *p, *q; for (p = words; *p != '\0'; p = q) { int quote = 0; while (isspace((unsigned char) *p)) { p++; } if (*p == '\0') { break; } ds_clear(&word); for (q = p; *q != '\0'; q++) { if (*q == quote) { quote = 0; } else if (*q == '\'' || *q == '"') { quote = *q; } else if (*q == '\\' && (!quote || quote == '"')) { q++; if (*q == '\0') { VLOG_WARN(LOG_MODULE, "%s: ends in trailing backslash", words); break; } ds_put_char(&word, *q); } else if (isspace((unsigned char) *q) && !quote) { q++; break; } else { ds_put_char(&word, *q); } } svec_add(svec, ds_cstr(&word)); if (quote) { VLOG_WARN(LOG_MODULE, "%s: word ends inside quoted string", words); } } ds_destroy(&word); }
static void ipf_print_reass_packet(const char *es, const void *pkt) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 10); if (!VLOG_DROP_WARN(&rl)) { struct ds ds = DS_EMPTY_INITIALIZER; ds_put_hex_dump(&ds, pkt, 128, 0, false); VLOG_WARN("%s\n%s", es, ds_cstr(&ds)); ds_destroy(&ds); } }
static int stream_open(struct stream *s) { ds_init(&s->log); if (pipe(s->fds)) { VLOG_WARN("failed to create pipe: %s", strerror(errno)); return errno; } set_nonblocking(s->fds[0]); return 0; }
/* Tries to make 'sock' stop listening to 'multicast_group'. Returns 0 if * successful, otherwise a positive errno value. * * Multicast group numbers are always positive. * * It is not an error to attempt to leave a multicast group to which a socket * does not belong. * * On success, reading from 'sock' will still return any messages that were * received on 'multicast_group' before the group was left. */ int nl_sock_leave_mcgroup(struct nl_sock *sock, unsigned int multicast_group) { if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &multicast_group, sizeof multicast_group) < 0) { VLOG_WARN("could not leave multicast group %u (%s)", multicast_group, ovs_strerror(errno)); return errno; } return 0; }
int main(int argc, char *argv[]) { enum ofputil_protocol usable_protocols; struct ofputil_flow_mod *fms = NULL; static struct classifier cls; struct cls_rule *rules; size_t n_fms, i; char *error; set_program_name(argv[0]); vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG); if (argc < 2) { usage(); } if (!strncmp(argv[1], "hsa", 3)) { VLOG_DBG("Enabling HSA"); cls.enable_hsa = true; } VLOG_DBG("using file: %s", argv[2]); error = parse_ofp_flow_mod_file(argv[2], OFPFC_ADD, &fms, &n_fms, &usable_protocols); if (error) { ovs_fatal(0, "%s", error); } classifier_init(&cls, flow_segment_u32s); fat_rwlock_wrlock(&cls.rwlock); rules = xmalloc(n_fms * sizeof *rules); for (i = 0; i < n_fms; i++) { struct cls_rule *rule = &rules[i]; struct cls_rule *displaced_rule; cls_rule_init(rule, &fms[i].match, fms[i].priority); displaced_rule = classifier_replace(&cls, rule); if (displaced_rule) { cls_rule_destroy(displaced_rule); VLOG_WARN("TODO"); } } fat_rwlock_unlock(&cls.rwlock); benchmark(&cls); free(rules); free(fms); return 0; }
/* Like fatal_signal_remove_file_to_unlink(), but also unlinks 'file'. * Returns 0 if successful, otherwise a positive errno value. */ int fatal_signal_unlink_file_now(const char *file) { int error = unlink(file) ? errno : 0; if (error) { VLOG_WARN("could not unlink \"%s\" (%s)", file, strerror(error)); } fatal_signal_remove_file_to_unlink(file); return error; }
static void fail_open_recover(struct fail_open *fo) { struct cls_rule rule; VLOG_WARN("No longer in fail-open mode"); fo->last_disconn_secs = 0; fo->next_bogus_packet_in = LLONG_MAX; cls_rule_init_catchall(&rule, FAIL_OPEN_PRIORITY); ofproto_delete_flow(fo->ofproto, &rule); }
/* Starts a subprocess with the arguments in the null-terminated argv[] array. * argv[0] is used as the name of the process. Searches the PATH environment * variable to find the program to execute. * * All file descriptors are closed before executing the subprocess, except for * fds 0, 1, and 2 and the 'n_keep_fds' fds listed in 'keep_fds'. Also, any of * the 'n_null_fds' fds listed in 'null_fds' are replaced by /dev/null. * * Returns 0 if successful, otherwise a positive errno value indicating the * error. If successful, '*pp' is assigned a new struct process that may be * used to query the process's status. On failure, '*pp' is set to NULL. */ int process_start(char **argv, const int keep_fds[], size_t n_keep_fds, const int null_fds[], size_t n_null_fds, struct process **pp) { sigset_t oldsigs; pid_t pid; int error; *pp = NULL; COVERAGE_INC(process_start); error = process_prestart(argv); if (error) { return error; } block_sigchld(&oldsigs); pid = fork(); if (pid < 0) { unblock_sigchld(&oldsigs); VLOG_WARN("fork failed: %s", strerror(errno)); return errno; } else if (pid) { /* Running in parent process. */ *pp = process_register(argv[0], pid); unblock_sigchld(&oldsigs); return 0; } else { /* Running in child process. */ int fd_max = get_max_fds(); int fd; fatal_signal_fork(); unblock_sigchld(&oldsigs); for (fd = 0; fd < fd_max; fd++) { if (is_member(fd, null_fds, n_null_fds)) { /* We can't use get_null_fd() here because we might have * already closed its fd. */ int nullfd = open("/dev/null", O_RDWR); dup2(nullfd, fd); close(nullfd); } else if (fd >= 3 && !is_member(fd, keep_fds, n_keep_fds)) { close(fd); } } execvp(argv[0], argv); fprintf(stderr, "execvp(\"%s\") failed: %s\n", argv[0], strerror(errno)); _exit(1); } }
static void log_poll_interval(long long int last_wakeup) { long long int interval = time_msec() - last_wakeup; if (interval >= 1000 && !is_warped(&monotonic_clock)) { const struct rusage *last_rusage = get_recent_rusage(); struct rusage rusage; getrusage(RUSAGE_SELF, &rusage); VLOG_WARN("Unreasonably long %lldms poll interval" " (%lldms user, %lldms system)", interval, timeval_diff_msec(&rusage.ru_utime, &last_rusage->ru_utime), timeval_diff_msec(&rusage.ru_stime, &last_rusage->ru_stime)); if (rusage.ru_minflt > last_rusage->ru_minflt || rusage.ru_majflt > last_rusage->ru_majflt) { VLOG_WARN("faults: %ld minor, %ld major", rusage.ru_minflt - last_rusage->ru_minflt, rusage.ru_majflt - last_rusage->ru_majflt); } if (rusage.ru_inblock > last_rusage->ru_inblock || rusage.ru_oublock > last_rusage->ru_oublock) { VLOG_WARN("disk: %ld reads, %ld writes", rusage.ru_inblock - last_rusage->ru_inblock, rusage.ru_oublock - last_rusage->ru_oublock); } if (rusage.ru_nvcsw > last_rusage->ru_nvcsw || rusage.ru_nivcsw > last_rusage->ru_nivcsw) { VLOG_WARN("context switches: %ld voluntary, %ld involuntary", rusage.ru_nvcsw - last_rusage->ru_nvcsw, rusage.ru_nivcsw - last_rusage->ru_nivcsw); } coverage_log(); } }
/* If a locked pidfile exists, issue a warning message and, unless * ignore_existing_pidfile() has been called, terminate the program. */ void die_if_already_running(void) { pid_t pid = already_running(); if (pid) { if (!overwrite_pidfile) { ovs_fatal(0, "%s: already running as pid %ld", get_pidfile(), (long int) pid); } else { VLOG_WARN("%s: %s already running as pid %ld", get_pidfile(), program_name, (long int) pid); } } }
/* Opens and reads a PID from 'pidfile'. Returns the nonnegative PID if * successful, otherwise a negative errno value. */ pid_t read_pidfile(const char *pidfile) { char line[128]; struct flock lck; FILE *file; int error; file = fopen(pidfile, "r"); if (!file) { error = errno; VLOG_WARN("%s: open: %s", pidfile, strerror(error)); goto error; } lck.l_type = F_WRLCK; lck.l_whence = SEEK_SET; lck.l_start = 0; lck.l_len = 0; if (fcntl(fileno(file), F_GETLK, &lck)) { error = errno; VLOG_WARN("%s: fcntl: %s", pidfile, strerror(error)); goto error; } if (lck.l_type == F_UNLCK) { error = ESRCH; VLOG_WARN("%s: pid file is not locked", pidfile); goto error; } if (!fgets(line, sizeof line, file)) { if (ferror(file)) { error = errno; VLOG_WARN("%s: read: %s", pidfile, strerror(error)); } else { error = ESRCH; VLOG_WARN("%s: read: unexpected end of file", pidfile); } goto error; } if (lck.l_pid != strtoul(line, NULL, 10)) { error = ESRCH; VLOG_WARN("l_pid (%ld) != %s pid (%s)", (long int) lck.l_pid, pidfile, line); goto error; } fclose(file); return lck.l_pid; error: if (file) { fclose(file); } return -error; }
/* Configure QOS COS maps for a particular bridge. */ void qos_configure_global_cos_map(struct ofproto *ofproto, struct ovsdb_idl *idl, unsigned int idl_seqno) { int n_modified; const struct ovsrec_qos_cos_map_entry *ovsrec_cos_map_entry; struct cos_map_settings cos_map_settings; /* How many rows in the COS map are modified? */ cos_map_settings.n_entries = 0; OVSREC_QOS_COS_MAP_ENTRY_FOR_EACH(ovsrec_cos_map_entry, idl) { if (OVSREC_IDL_IS_ROW_MODIFIED(ovsrec_cos_map_entry, idl_seqno) || OVSREC_IDL_IS_ROW_INSERTED(ovsrec_cos_map_entry, idl_seqno)) { VLOG_DBG("%s: MODIFIED %s %d", __FUNCTION__, ovsrec_cos_map_entry->description, (int)ovsrec_cos_map_entry->code_point); cos_map_settings.n_entries++; } } if (cos_map_settings.n_entries > 0) { /* build the settings struct, call provider API */ cos_map_settings.entries = malloc(sizeof(struct cos_map_entry) * cos_map_settings.n_entries); if (cos_map_settings.entries == NULL) { /* Out of memory, get out. Called again at next notification. */ return; } n_modified = 0; OVSREC_QOS_COS_MAP_ENTRY_FOR_EACH(ovsrec_cos_map_entry, idl) { if (OVSREC_IDL_IS_ROW_MODIFIED(ovsrec_cos_map_entry, idl_seqno) || OVSREC_IDL_IS_ROW_INSERTED(ovsrec_cos_map_entry, idl_seqno)) { cos_map_settings.entries[n_modified].color = qos_get_color(ovsrec_cos_map_entry->color); cos_map_settings.entries[n_modified].codepoint = ovsrec_cos_map_entry->code_point; cos_map_settings.entries[n_modified].local_priority = ovsrec_cos_map_entry->local_priority; n_modified++; } } if (n_modified != cos_map_settings.n_entries) { VLOG_WARN("%s: mismatched cos_map request rows_chgd=%d != modified=%d", __FUNCTION__, cos_map_settings.n_entries, n_modified); } ofproto_set_cos_map(ofproto, NULL, &cos_map_settings); free(cos_map_settings.entries); }
/* Tries to add 'sock' as a listener for 'multicast_group'. Returns 0 if * successful, otherwise a positive errno value. * * A socket that is subscribed to a multicast group that receives asynchronous * notifications must not be used for Netlink transactions or dumps, because * transactions and dumps can cause notifications to be lost. * * Multicast group numbers are always positive. * * It is not an error to attempt to join a multicast group to which a socket * already belongs. */ int nl_sock_join_mcgroup(struct nl_sock *sock, unsigned int multicast_group) { int error = nl_sock_cow__(sock); if (error) { return error; } if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &multicast_group, sizeof multicast_group) < 0) { VLOG_WARN("could not join multicast group %u (%s)", multicast_group, strerror(errno)); return errno; } return 0; }
uint32_t ofputil_versions_from_strings(char ** const s, size_t count) { uint32_t bitmap = 0; while (count--) { int version = ofputil_version_from_string(s[count]); if (!version) { VLOG_WARN("Unknown OpenFlow version: \"%s\"", s[count]); } else { bitmap |= 1u << version; } } return bitmap; }
static bool switch_status_remote_packet_cb(struct relay *r, void *ss_) { struct switch_status *ss = ss_; struct rconn *rc = r->halves[HALF_REMOTE].rconn; struct ofpbuf *msg = r->halves[HALF_REMOTE].rxbuf; struct switch_status_category *c; struct nicira_header *request; struct nicira_header *reply; struct status_reply sr; struct ofpbuf *b; int retval; if (msg->size < sizeof(struct nicira_header)) { return false; } request = msg->data; if (request->header.type != OFPT_EXPERIMENTER || request->vendor != htonl(NX_VENDOR_ID) || request->subtype != htonl(NXT_STATUS_REQUEST)) { return false; } sr.request.string = (void *) (request + 1); sr.request.length = msg->size - sizeof *request; ds_init(&sr.output); for (c = ss->categories; c < &ss->categories[ss->n_categories]; c++) { if (!memcmp(c->name, sr.request.string, MIN(strlen(c->name), sr.request.length))) { sr.category = c; c->cb(&sr, c->aux); } } reply = make_openflow_xid(sizeof *reply + sr.output.length, OFPT_EXPERIMENTER, request->header.xid, &b); reply->vendor = htonl(NX_VENDOR_ID); reply->subtype = htonl(NXT_STATUS_REPLY); memcpy(reply + 1, sr.output.string, sr.output.length); retval = rconn_send(rc, b, NULL); if (retval && retval != EAGAIN) { VLOG_WARN(LOG_MODULE, "send failed (%s)", strerror(retval)); } ds_destroy(&sr.output); return true; }
/* Check whether a fatal signal has occurred and, if so, call the fatal signal * hooks and exit. * * This function is called automatically by poll_block(), but specialized * programs that may not always call poll_block() on a regular basis should * also call it periodically. (Therefore, any function with "block" in its * name should call fatal_signal_run() each time it is called, either directly * or through poll_block(), because such functions can only used by specialized * programs that can afford to block outside their main loop around * poll_block().) */ void fatal_signal_run(void) { sig_atomic_t sig_nr; fatal_signal_init(); sig_nr = stored_sig_nr; if (sig_nr != SIG_ATOMIC_MAX) { VLOG_WARN("terminating with signal %d (%s)", (int)sig_nr, signal_name(sig_nr)); call_hooks(sig_nr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); } }
/* Like fatal_signal_remove_file_to_unlink(), but also unlinks 'file'. * Returns 0 if successful, otherwise a positive errno value. */ int fatal_signal_unlink_file_now(const char *file) { int error; fatal_signal_init(); ovs_mutex_lock(&mutex); error = unlink(file) ? errno : 0; if (error) { VLOG_WARN("could not unlink \"%s\" (%s)", file, ovs_strerror(error)); } fatal_signal_remove_file_to_unlink(file); ovs_mutex_unlock(&mutex); return error; }