/* Extracts the mac, IPv4 and IPv6 addresses from the * "nbrec_logical_router_port" parameter 'lrp'. Stores the IPv4 and * IPv6 addresses in the 'ipv4_addrs' and 'ipv6_addrs' fields of * 'laddrs', respectively. In addition, a link local IPv6 address * based on the 'mac' member of 'lrp' is added to the 'ipv6_addrs' * field. * * Return true if a valid 'mac' address is found in 'lrp', false otherwise. * * The caller must call destroy_lport_addresses(). */ bool extract_lrp_networks(const struct nbrec_logical_router_port *lrp, struct lport_addresses *laddrs) { memset(laddrs, 0, sizeof *laddrs); if (!eth_addr_from_string(lrp->mac, &laddrs->ea)) { laddrs->ea = eth_addr_zero; return false; } snprintf(laddrs->ea_s, sizeof laddrs->ea_s, ETH_ADDR_FMT, ETH_ADDR_ARGS(laddrs->ea)); for (int i = 0; i < lrp->n_networks; i++) { ovs_be32 ip4; struct in6_addr ip6; unsigned int plen; char *error; error = ip_parse_cidr(lrp->networks[i], &ip4, &plen); if (!error) { if (!ip4 || plen == 32) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); VLOG_WARN_RL(&rl, "bad 'networks' %s", lrp->networks[i]); continue; } add_ipv4_netaddr(laddrs, ip4, plen); continue; } free(error); error = ipv6_parse_cidr(lrp->networks[i], &ip6, &plen); if (!error) { if (plen == 128) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); VLOG_WARN_RL(&rl, "bad 'networks' %s", lrp->networks[i]); continue; } add_ipv6_netaddr(laddrs, ip6, plen); } else { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_INFO_RL(&rl, "invalid syntax '%s' in networks", lrp->networks[i]); free(error); } } /* Always add the IPv6 link local address. */ struct in6_addr lla; in6_generate_lla(laddrs->ea, &lla); add_ipv6_netaddr(laddrs, lla, 64); return true; }
enum ofperr ofputil_decode_bundle_add(const struct ofp_header *oh, struct ofputil_bundle_add_msg *msg, enum ofptype *typep) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); /* Pull the outer ofp_header. */ enum ofpraw raw = ofpraw_pull_assert(&b); ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE || raw == OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE); /* Pull the bundle_ctrl header. */ const struct ofp14_bundle_ctrl_msg *m = ofpbuf_pull(&b, sizeof *m); msg->bundle_id = ntohl(m->bundle_id); msg->flags = ntohs(m->flags); /* Pull the inner ofp_header. */ if (b.size < sizeof(struct ofp_header)) { return OFPERR_OFPBFC_MSG_BAD_LEN; } msg->msg = b.data; if (msg->msg->version != oh->version) { return OFPERR_OFPBFC_BAD_VERSION; } size_t inner_len = ntohs(msg->msg->length); if (inner_len < sizeof(struct ofp_header) || inner_len > b.size) { return OFPERR_OFPBFC_MSG_BAD_LEN; } if (msg->msg->xid != oh->xid) { return OFPERR_OFPBFC_MSG_BAD_XID; } /* Reject unbundlable messages. */ enum ofptype type; enum ofperr error = ofptype_decode(&type, msg->msg); if (error) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_WARN_RL(&rl, "OFPT14_BUNDLE_ADD_MESSAGE contained " "message is unparsable (%s)", ofperr_get_name(error)); return OFPERR_OFPBFC_MSG_UNSUP; /* 'error' would be confusing. */ } if (!ofputil_is_bundlable(type)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_WARN_RL(&rl, "%s message not allowed inside " "OFPT14_BUNDLE_ADD_MESSAGE", ofptype_get_name(type)); return OFPERR_OFPBFC_MSG_UNSUP; } if (typep) { *typep = type; } return 0; }
int check_connection_completion(int fd) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 10); struct pollfd pfd; int retval; pfd.fd = fd; pfd.events = POLLOUT; #ifndef _WIN32 do { retval = poll(&pfd, 1, 0); } while (retval < 0 && errno == EINTR); #else retval = WSAPoll(&pfd, 1, 0); #endif if (retval == 1) { if (pfd.revents & POLLERR) { ssize_t n = send(fd, "", 1, 0); if (n < 0) { return sock_errno(); } else { VLOG_ERR_RL(&rl, "poll return POLLERR but send succeeded"); return EPROTO; } } return 0; } else if (retval < 0) { VLOG_ERR_RL(&rl, "poll: %s", sock_strerror(sock_errno())); return errno; } else { return EAGAIN; } }
static void resize(struct hmap *hmap, size_t new_mask, const char *where) { struct hmap tmp; size_t i; ovs_assert(is_pow2(new_mask + 1)); hmap_init(&tmp); if (new_mask) { tmp.buckets = xmalloc(sizeof *tmp.buckets * (new_mask + 1)); tmp.mask = new_mask; for (i = 0; i <= tmp.mask; i++) { tmp.buckets[i] = NULL; } } for (i = 0; i <= hmap->mask; i++) { struct hmap_node *node, *next; int count = 0; for (node = hmap->buckets[i]; node; node = next) { next = node->next; hmap_insert_fast(&tmp, node, node->hash); count++; } if (count > 5) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 10); COVERAGE_INC(hmap_pathological); VLOG_DBG_RL(&rl, "%s: %d nodes in bucket (%"PRIuSIZE" nodes, %"PRIuSIZE" buckets)", where, count, hmap->n, hmap->mask + 1); } } hmap_swap(hmap, &tmp); hmap_destroy(&tmp); }
/* Perform all of the per-loop processing. */ static void daemon_run(void) { unsigned int new_idl_seqno = ovsdb_idl_get_seqno(idl); ovsdb_idl_run(idl); if (ovsdb_idl_is_lock_contended(idl)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_ERR_RL(&rl, "another ops-usermgmt process is running, " "disabling this process until it goes away"); return; } else if (!ovsdb_idl_has_lock(idl)) { return; } /* Acquired lock, we're officially ops-usermgmt now. */ if (!populated) { /* First time we got this far, populate database from passwd. */ if (sync_to_db()) populated = true; daemonize_complete(); vlog_enable_async(); VLOG_INFO_ONCE("%s (OpenSwitch usermgmt)", program_name); } if (new_idl_seqno == idl_seqno) return; /* Change in OVSDB detected. */ idl_seqno = new_idl_seqno; sync_from_db(); }
enum ofperr bundle_check(const struct ofpact_bundle *bundle, ofp_port_t max_ports, const struct flow *flow) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); size_t i; if (bundle->dst.field) { enum ofperr error = mf_check_dst(&bundle->dst, flow); if (error) { return error; } } for (i = 0; i < bundle->n_slaves; i++) { ofp_port_t ofp_port = bundle->slaves[i]; enum ofperr error; error = ofpact_check_output_port(ofp_port, max_ports); if (error) { VLOG_WARN_RL(&rl, "invalid slave %"PRIu16, ofp_port); return error; } /* Controller slaves are unsupported due to the lack of a max_len * argument. This may or may not change in the future. There doesn't * seem to be a real-world use-case for supporting it. */ if (ofp_port == OFPP_CONTROLLER) { VLOG_WARN_RL(&rl, "unsupported controller slave"); return OFPERR_OFPBAC_BAD_OUT_PORT; } } return 0; }
void classifierd_run(void) { struct ovsdb_idl_txn *txn; /* Process a batch of messages from OVSDB. */ ovsdb_idl_run(idl); if (ovsdb_idl_is_lock_contended(idl)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_ERR_RL(&rl, "Another classifierd process is running, " "disabling this process until it goes away"); return; } else if (!ovsdb_idl_has_lock(idl)) { return; } /* Nothing to do until system has been configured, i.e. cur_cfg > 0. */ if (!classifierd_system_is_configured()) { return; } /* Update the local configuration and push any changes to the dB. */ txn = ovsdb_idl_txn_create(idl); if (classifierd_reconfigure()) { VLOG_DBG("%s: Committing changes\n",__FUNCTION__); /* Some OVSDB write needs to happen. */ ovsdb_idl_txn_commit_block(txn); } ovsdb_idl_txn_destroy(txn); return; } /* classifierd_run */
/* Attempts to make 'ml' learn from the fact that a frame from 'src_mac' was * just observed arriving from 'src_port' on the given 'vlan'. * * Returns nonzero if we actually learned something from this, zero if it just * confirms what we already knew. The nonzero return value is the tag of flows * that now need revalidation. * * The 'vlan' parameter is used to maintain separate per-VLAN learning tables. * Specify 0 if this behavior is undesirable. * * 'lock_type' specifies whether the entry should be locked or existing locks * are check. */ tag_type mac_learning_learn(struct mac_learning *ml, const uint8_t src_mac[ETH_ADDR_LEN], uint16_t vlan, uint16_t src_port, enum grat_arp_lock_type lock_type) { struct mac_entry *e; struct list *bucket; if (!is_learning_vlan(ml, vlan)) { return 0; } if (eth_addr_is_multicast(src_mac)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 30); VLOG_DBG_RL(&rl, "multicast packet source "ETH_ADDR_FMT, ETH_ADDR_ARGS(src_mac)); return 0; } bucket = mac_table_bucket(ml, src_mac, vlan); e = search_bucket(bucket, src_mac, vlan); if (!e) { if (!list_is_empty(&ml->free)) { e = mac_entry_from_lru_node(ml->free.next); } else { e = mac_entry_from_lru_node(ml->lrus.next); list_remove(&e->hash_node); } memcpy(e->mac, src_mac, ETH_ADDR_LEN); list_push_front(bucket, &e->hash_node); e->port = -1; e->vlan = vlan; e->tag = make_unknown_mac_tag(ml, src_mac, vlan); e->grat_arp_lock = TIME_MIN; } if (lock_type != GRAT_ARP_LOCK_CHECK || time_now() >= e->grat_arp_lock) { /* Make the entry most-recently-used. */ list_remove(&e->lru_node); list_push_back(&ml->lrus, &e->lru_node); e->expires = time_now() + MAC_ENTRY_IDLE_TIME; if (lock_type == GRAT_ARP_LOCK_SET) { e->grat_arp_lock = time_now() + MAC_GRAT_ARP_LOCK_TIME; } /* Did we learn something? */ if (e->port != src_port) { tag_type old_tag = e->tag; e->port = src_port; e->tag = tag_create_random(); COVERAGE_INC(mac_learning_learned); return old_tag; } } return 0; }
/* Translates 'host_name', which must be a string representation of an IPv6 * address, into a numeric IPv6 address in '*addr'. Returns 0 if successful, * otherwise a positive errno value. */ int lookup_ipv6(const char *host_name, struct in6_addr *addr) { if (!ipv6_parse(host_name, addr)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_ERR_RL(&rl, "\"%s\" is not a valid IPv6 address", host_name); return ENOENT; } return 0; }
/* Translates 'host_name', which must be a string representation of an IP * address, into a numeric IP address in '*addr'. Returns 0 if successful, * otherwise a positive errno value. */ int lookup_ip(const char *host_name, struct in_addr *addr) { if (!inet_pton(AF_INET, host_name, addr)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_ERR_RL(&rl, "\"%s\" is not a valid IP address", host_name); return ENOENT; } return 0; }
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); } }
/* Extracts the mac, IPv4 and IPv6 addresses from * 'address' which * should be of the format 'MAC [IP1 IP2 ..]" where IPn should be a * valid IPv4 or IPv6 address and stores them in the 'ipv4_addrs' and * 'ipv6_addrs' fields of 'laddrs'. * * Return true if at least 'MAC' is found in 'address', false otherwise. * * The caller must call destroy_lport_addresses(). */ bool extract_lsp_addresses(const char *address, struct lport_addresses *laddrs) { int ofs; bool success = extract_addresses(address, laddrs, &ofs); if (success && ofs < strlen(address)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_INFO_RL(&rl, "invalid syntax '%s' in address", address); } return success; }
static const char * get_chassis_id(const struct ovsdb_idl *ovs_idl) { const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl); const char *chassis_id = cfg ? smap_get(&cfg->external_ids, "system-id") : NULL; if (!chassis_id) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); VLOG_WARN_RL(&rl, "'system-id' in Open_vSwitch database is missing."); } return chassis_id; }
int check_connection_completion(int fd) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 10); struct pollfd pfd; int retval; pfd.fd = fd; pfd.events = POLLOUT; #ifndef _WIN32 do { retval = poll(&pfd, 1, 0); } while (retval < 0 && errno == EINTR); #else fd_set wrset, exset; FD_ZERO(&wrset); FD_ZERO(&exset); FD_SET(fd, &exset); FD_SET(fd, &wrset); pfd.revents = 0; struct timeval tv = { 0, 0 }; /* WSAPoll is broken on Windows, instead do a select */ retval = select(0, NULL, &wrset, &exset, &tv); if (retval == 1) { if (FD_ISSET(fd, &wrset)) { pfd.revents |= pfd.events; } if (FD_ISSET(fd, &exset)) { pfd.revents |= POLLERR; } } #endif if (retval == 1) { if (pfd.revents & POLLERR) { ssize_t n = send(fd, "", 1, 0); if (n < 0) { return sock_errno(); } else { VLOG_ERR_RL(&rl, "poll return POLLERR but send succeeded"); return EPROTO; } } return 0; } else if (retval < 0) { VLOG_ERR_RL(&rl, "poll: %s", sock_strerror(sock_errno())); return errno; } else { return EAGAIN; } }
/* Extracts the mac, IPv4 and IPv6 addresses from * 'address' which * should be of the format 'MAC [IP1 IP2 ..]" where IPn should be a * valid IPv4 or IPv6 address and stores them in the 'ipv4_addrs' and * 'ipv6_addrs' fields of 'laddrs'. * * Return true if at least 'MAC' is found in 'address', false otherwise. * * The caller must call destroy_lport_addresses(). */ bool extract_lsp_addresses(const char *address, struct lport_addresses *laddrs) { memset(laddrs, 0, sizeof *laddrs); const char *buf = address; int buf_index = 0; const char *buf_end = buf + strlen(address); if (!ovs_scan_len(buf, &buf_index, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(laddrs->ea))) { laddrs->ea = eth_addr_zero; return false; } snprintf(laddrs->ea_s, sizeof laddrs->ea_s, ETH_ADDR_FMT, ETH_ADDR_ARGS(laddrs->ea)); ovs_be32 ip4; struct in6_addr ip6; unsigned int plen; char *error; /* Loop through the buffer and extract the IPv4/IPv6 addresses * and store in the 'laddrs'. Break the loop if invalid data is found. */ buf += buf_index; while (buf < buf_end) { buf_index = 0; error = ip_parse_cidr_len(buf, &buf_index, &ip4, &plen); if (!error) { add_ipv4_netaddr(laddrs, ip4, plen); buf += buf_index; continue; } free(error); error = ipv6_parse_cidr_len(buf, &buf_index, &ip6, &plen); if (!error) { add_ipv6_netaddr(laddrs, ip6, plen); } else { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_INFO_RL(&rl, "invalid syntax '%s' in address", address); free(error); break; } buf += buf_index; } return true; }
static void update_ct_zones(struct sset *lports, struct simap *ct_zones, unsigned long *ct_zone_bitmap) { struct simap_node *ct_zone, *ct_zone_next; const char *iface_id; int scan_start = 1; /* xxx This is wasteful to assign a zone to each port--even if no * xxx security policy is applied. */ /* Delete any zones that are associated with removed ports. */ SIMAP_FOR_EACH_SAFE(ct_zone, ct_zone_next, ct_zones) { if (!sset_contains(lports, ct_zone->name)) { bitmap_set0(ct_zone_bitmap, ct_zone->data); simap_delete(ct_zones, ct_zone); } } /* Assign a unique zone id for each logical port. */ SSET_FOR_EACH(iface_id, lports) { size_t zone; if (simap_contains(ct_zones, iface_id)) { continue; } /* We assume that there are 64K zones and that we own them all. */ zone = bitmap_scan(ct_zone_bitmap, 0, scan_start, MAX_CT_ZONES + 1); if (zone == MAX_CT_ZONES + 1) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_WARN_RL(&rl, "exhausted all ct zones"); return; } scan_start = zone + 1; bitmap_set1(ct_zone_bitmap, zone); simap_put(ct_zones, iface_id, zone); /* xxx We should erase any old entries for this * xxx zone, but we need a generic interface to the conntrack * xxx table. */ }
static const struct ovsrec_bridge * get_br_int(struct ovsdb_idl *ovs_idl) { const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl); if (!cfg) { return NULL; } const char *br_int_name = smap_get(&cfg->external_ids, "ovn-bridge"); if (!br_int_name) { br_int_name = DEFAULT_BRIDGE_NAME; } const struct ovsrec_bridge *br; OVSREC_BRIDGE_FOR_EACH (br, ovs_idl) { if (!strcmp(br->name, br_int_name)) { return br; } } static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_WARN_RL(&rl, "%s: integration bridge does not exist", br_int_name); return NULL; }
#include "coverage.h" #include "fatal-signal.h" #include "netdev-provider.h" #include "openvswitch/ofpbuf.h" #include "packets.h" #include "poll-loop.h" #include "openvswitch/shash.h" #include "svec.h" #include "openvswitch/vlog.h" #include "odp-netlink.h" #include "netlink-socket.h" #include "netlink.h" VLOG_DEFINE_THIS_MODULE(netdev_windows); static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5); enum { VALID_ETHERADDR = 1 << 0, VALID_MTU = 1 << 1, VALID_IFFLAG = 1 << 5, }; /* Caches the information of a netdev. */ struct netdev_windows { struct netdev up; int32_t dev_type; uint32_t port_no; unsigned int change_seq;
/* Blocks until one or more of the events registered with poll_fd_wait() * occurs, or until the minimum duration registered with poll_timer_wait() * elapses, or not at all if poll_immediate_wake() has been called. * * Also executes any autonomous subroutines registered with poll_fd_callback(), * if their file descriptors have become ready. */ void poll_block(void) { static struct pollfd *pollfds; static size_t max_pollfds; struct poll_waiter *pw; struct list *node; int n_pollfds; int retval; assert(!running_cb); if (max_pollfds < n_waiters) { max_pollfds = n_waiters; pollfds = xrealloc(pollfds, max_pollfds * sizeof *pollfds); } n_pollfds = 0; LIST_FOR_EACH (pw, struct poll_waiter, node, &waiters) { pw->pollfd = &pollfds[n_pollfds]; pollfds[n_pollfds].fd = pw->fd; pollfds[n_pollfds].events = pw->events; pollfds[n_pollfds].revents = 0; n_pollfds++; } retval = time_poll(pollfds, n_pollfds, timeout); if (retval < 0) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_ERR_RL(&rl, "poll: %s", strerror(-retval)); } else if (!retval && VLOG_IS_DBG_ENABLED()) { log_wakeup(&timeout_backtrace, "%d-ms timeout", timeout); } for (node = waiters.next; node != &waiters; ) { pw = CONTAINER_OF(node, struct poll_waiter, node); if (!pw->pollfd || !pw->pollfd->revents) { if (pw->function) { node = node->next; continue; } } else { if (VLOG_IS_DBG_ENABLED()) { log_wakeup(pw->backtrace, "%s%s%s%s%s on fd %d", pw->pollfd->revents & POLLIN ? "[POLLIN]" : "", pw->pollfd->revents & POLLOUT ? "[POLLOUT]" : "", pw->pollfd->revents & POLLERR ? "[POLLERR]" : "", pw->pollfd->revents & POLLHUP ? "[POLLHUP]" : "", pw->pollfd->revents & POLLNVAL ? "[POLLNVAL]" : "", pw->fd); } if (pw->function) { #ifndef NDEBUG running_cb = pw; #endif pw->function(pw->fd, pw->pollfd->revents, pw->aux); #ifndef NDEBUG running_cb = NULL; #endif } } node = node->next; poll_cancel(pw); } timeout = -1; timeout_backtrace.n_frames = 0; }
#define DPDK_DEBUG() VLOG_DBG_RL(&dpmsg_rl, "%s: %s Line %d\n", __FILE__, __FUNCTION__, __LINE__); #define BR_PREFIX_LEN 2 #define BR_PREFIX "br" #define DPIF_SOCKNAME "\0dpif-dpdk" #define SIGNAL_HANDLED(sock_fd, sock_msg) \ do { \ recvfrom(sock_fd, &sock_msg, sizeof(sock_msg), 0, NULL, NULL); \ } while (0) VLOG_DEFINE_THIS_MODULE(dpif_dpdk); static int dpdk_sock = -1; static struct vlog_rate_limit dpmsg_rl = VLOG_RATE_LIMIT_INIT(600, 600); static void dpif_dpdk_flow_init(struct dpif_dpdk_flow_message *); static int dpif_dpdk_flow_transact(struct dpif_dpdk_flow_message *request, struct dpif_dpdk_flow_message *reply); static void dpif_dpdk_flow_get_stats(const struct dpif_dpdk_flow_message *, struct dpif_flow_stats *); static void dpif_dpdk_flow_key_from_flow(struct dpif_dpdk_flow_key *, const struct flow *); static void dpif_dpdk_flow_key_to_flow(const struct dpif_dpdk_flow_key *, struct flow *); static void dpif_dpdk_flow_actions_to_actions(const struct dpif_dpdk_action *, struct ofpbuf *); static int dpif_dpdk_init(void); static void flow_message_get_create(const struct dpif *dpif_ OVS_UNUSED, const struct nlattr *key, size_t key_len,
/* Checks that 'nab' specifies a bundle action which is supported by this * bundle module. Uses the 'max_ports' parameter to validate each port using * ofputil_check_output_port(). Returns 0 if 'nab' is supported, otherwise an * OpenFlow error code (as returned by ofp_mkerr()). */ int bundle_check(const struct nx_action_bundle *nab, int max_ports, const struct flow *flow) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); uint16_t n_slaves, fields, algorithm, subtype; uint32_t slave_type; size_t slaves_size, i; int error; subtype = ntohs(nab->subtype); n_slaves = ntohs(nab->n_slaves); fields = ntohs(nab->fields); algorithm = ntohs(nab->algorithm); slave_type = ntohl(nab->slave_type); slaves_size = ntohs(nab->len) - sizeof *nab; error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); if (!flow_hash_fields_valid(fields)) { VLOG_WARN_RL(&rl, "unsupported fields %"PRIu16, fields); } else if (n_slaves > BUNDLE_MAX_SLAVES) { VLOG_WARN_RL(&rl, "too may slaves"); } else if (algorithm != NX_BD_ALG_HRW && algorithm != NX_BD_ALG_ACTIVE_BACKUP) { VLOG_WARN_RL(&rl, "unsupported algorithm %"PRIu16, algorithm); } else if (slave_type != NXM_OF_IN_PORT) { VLOG_WARN_RL(&rl, "unsupported slave type %"PRIu16, slave_type); } else { error = 0; } for (i = 0; i < sizeof(nab->zero); i++) { if (nab->zero[i]) { VLOG_WARN_RL(&rl, "reserved field is nonzero"); error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); } } if (subtype == NXAST_BUNDLE && (nab->ofs_nbits || nab->dst)) { VLOG_WARN_RL(&rl, "bundle action has nonzero reserved fields"); error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); } if (subtype == NXAST_BUNDLE_LOAD) { int ofs = nxm_decode_ofs(nab->ofs_nbits); int n_bits = nxm_decode_n_bits(nab->ofs_nbits); if (n_bits < 16) { VLOG_WARN_RL(&rl, "bundle_load action requires at least 16 bit " "destination."); error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); } else { error = nxm_dst_check(nab->dst, ofs, n_bits, flow) || error; } } if (slaves_size < n_slaves * sizeof(ovs_be16)) { VLOG_WARN_RL(&rl, "Nicira action %"PRIu16" only has %zu bytes " "allocated for slaves. %zu bytes are required for " "%"PRIu16" slaves.", subtype, slaves_size, n_slaves * sizeof(ovs_be16), n_slaves); error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } for (i = 0; i < n_slaves; i++) { uint16_t ofp_port = bundle_get_slave(nab, i); int ofputil_error = ofputil_check_output_port(ofp_port, max_ports); if (ofputil_error) { VLOG_WARN_RL(&rl, "invalid slave %"PRIu16, ofp_port); error = ofputil_error; } /* Controller slaves are unsupported due to the lack of a max_len * argument. This may or may not change in the future. There doesn't * seem to be a real-world use-case for supporting it. */ if (ofp_port == OFPP_CONTROLLER) { VLOG_WARN_RL(&rl, "unsupported controller slave"); error = ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT); } } return error; }
struct rconn; #include "mpls-fib.h" #include "mpls-switch.h" #include "read-mpls-fib.h" #define THIS_MODULE VLM_mpls_switch #include "vlog.h" // MAH: start // XXX TEMPORARY #include "vconn-mpls.h" // MAH: end /* The log messages here could actually be useful in debugging, so keep the * rate limit relatively high. */ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300); static void send_features_request(struct mpls_switch *sw, struct rconn *rconn); void queue_tx(struct mpls_switch *, struct rconn *, struct ofpbuf *); static void send_features_request(struct mpls_switch *, struct rconn *); static void schedule_query(struct mpls_switch *, long long int delay); typedef void packet_handler_func(struct mpls_switch *, struct rconn *, void *); static packet_handler_func process_switch_features; static packet_handler_func process_packet_in; static packet_handler_func process_echo_request; static packet_handler_func process_port_status; static packet_handler_func process_phy_port; static packet_handler_func process_stats_reply;
static struct ofpbuf * ofperr_encode_msg__(enum ofperr error, enum ofp_version ofp_version, ovs_be32 xid, const void *data, size_t data_len) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); const struct ofperr_domain *domain; const struct triplet *triplet; struct ofp_error_msg *oem; struct ofpbuf *buf; /* Get the error domain for 'ofp_version', or fall back to OF1.0. */ domain = ofperr_domain_from_version(ofp_version); if (!domain) { VLOG_ERR_RL(&rl, "cannot encode error for unknown OpenFlow " "version 0x%02x", ofp_version); domain = &ofperr_of10; } /* Make sure 'error' is valid in 'domain', or use a fallback error. */ if (!ofperr_is_valid(error)) { /* 'error' seems likely to be a system errno value. */ VLOG_ERR_RL(&rl, "invalid OpenFlow error code %d (%s)", error, ovs_strerror(error)); error = OFPERR_NXBRC_UNENCODABLE_ERROR; } else if (domain->errors[error - OFPERR_OFS].code < 0) { VLOG_ERR_RL(&rl, "cannot encode %s for %s", ofperr_get_name(error), domain->name); error = OFPERR_NXBRC_UNENCODABLE_ERROR; } triplet = ofperr_get_triplet__(error, domain); if (!triplet->vendor) { buf = ofpraw_alloc_xid(OFPRAW_OFPT_ERROR, domain->version, xid, sizeof *oem + data_len); oem = ofpbuf_put_uninit(buf, sizeof *oem); oem->type = htons(triplet->type); oem->code = htons(triplet->code); } else if (ofp_version <= OFP11_VERSION) { struct nx_vendor_error *nve; buf = ofpraw_alloc_xid(OFPRAW_OFPT_ERROR, domain->version, xid, sizeof *oem + sizeof *nve + data_len); oem = ofpbuf_put_uninit(buf, sizeof *oem); oem->type = htons(NXET_VENDOR); oem->code = htons(NXVC_VENDOR_ERROR); nve = ofpbuf_put_uninit(buf, sizeof *nve); nve->vendor = htonl(triplet->vendor); nve->type = htons(triplet->type); nve->code = htons(triplet->code); } else { ovs_be32 vendor = htonl(triplet->vendor); buf = ofpraw_alloc_xid(OFPRAW_OFPT_ERROR, domain->version, xid, sizeof *oem + sizeof(uint32_t) + data_len); oem = ofpbuf_put_uninit(buf, sizeof *oem); oem->type = htons(OFPET12_EXPERIMENTER); oem->code = htons(triplet->type); ofpbuf_put(buf, &vendor, sizeof vendor); } ofpbuf_put(buf, data, MIN(data_len, UINT16_MAX - buf->size)); ofpmsg_update_length(buf); return buf; }
#define LOG_MODULE VLM_vconn_stream /* Active stream socket vconn. */ struct stream_vconn { struct vconn vconn; int fd; struct ofpbuf *rxbuf; struct ofpbuf *txbuf; struct poll_waiter *tx_waiter; }; static struct vconn_class stream_vconn_class; static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 25); static void stream_clear_txbuf(struct stream_vconn *); int new_stream_vconn(const char *name, int fd, int connect_status, uint32_t ip, bool reconnectable, struct vconn **vconnp) { struct stream_vconn *s; s = xmalloc(sizeof *s); vconn_init(&s->vconn, &stream_vconn_class, connect_status, ip, name, reconnectable); s->fd = fd; s->txbuf = NULL; s->tx_waiter = NULL;
#include <sys/types.h> #include "compiler.h" #include "group_table.h" #include "datapath.h" #include "dp_actions.h" #include "hmap.h" #include "packet.h" #include "util.h" #include "openflow/openflow.h" #include "oflib/ofl.h" #include "oflib/ofl-messages.h" #include "vlog.h" #define LOG_MODULE VLM_group_t static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 60); static bool is_loop_free(struct group_table *table, struct group_entry *mod_entry); struct group_entry * group_table_find(struct group_table *table, uint32_t group_id) { struct hmap_node *hnode; hnode = hmap_first_with_hash(&table->entries, group_id); if (hnode == NULL) { return NULL; }
/* Checks that 'nab' specifies a bundle action which is supported by this * bundle module. Uses the 'max_ports' parameter to validate each port using * ofputil_check_output_port(). Returns 0 if 'nab' is supported, otherwise an * OFPERR_* error code. */ enum ofperr bundle_from_openflow(const struct nx_action_bundle *nab, struct ofpbuf *ofpacts) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); struct ofpact_bundle *bundle; uint16_t subtype; uint32_t slave_type; size_t slaves_size, i; enum ofperr error; bundle = ofpact_put_BUNDLE(ofpacts); subtype = ntohs(nab->subtype); bundle->n_slaves = ntohs(nab->n_slaves); bundle->basis = ntohs(nab->basis); bundle->fields = ntohs(nab->fields); bundle->algorithm = ntohs(nab->algorithm); slave_type = ntohl(nab->slave_type); slaves_size = ntohs(nab->len) - sizeof *nab; error = OFPERR_OFPBAC_BAD_ARGUMENT; if (!flow_hash_fields_valid(bundle->fields)) { VLOG_WARN_RL(&rl, "unsupported fields %d", (int) bundle->fields); } else if (bundle->n_slaves > BUNDLE_MAX_SLAVES) { VLOG_WARN_RL(&rl, "too may slaves"); } else if (bundle->algorithm != NX_BD_ALG_HRW && bundle->algorithm != NX_BD_ALG_ACTIVE_BACKUP) { VLOG_WARN_RL(&rl, "unsupported algorithm %d", (int) bundle->algorithm); } else if (slave_type != NXM_OF_IN_PORT) { VLOG_WARN_RL(&rl, "unsupported slave type %"PRIu16, slave_type); } else { error = 0; } if (!is_all_zeros(nab->zero, sizeof nab->zero)) { VLOG_WARN_RL(&rl, "reserved field is nonzero"); error = OFPERR_OFPBAC_BAD_ARGUMENT; } if (subtype == NXAST_BUNDLE && (nab->ofs_nbits || nab->dst)) { VLOG_WARN_RL(&rl, "bundle action has nonzero reserved fields"); error = OFPERR_OFPBAC_BAD_ARGUMENT; } if (subtype == NXAST_BUNDLE_LOAD) { bundle->dst.field = mf_from_nxm_header(ntohl(nab->dst)); bundle->dst.ofs = nxm_decode_ofs(nab->ofs_nbits); bundle->dst.n_bits = nxm_decode_n_bits(nab->ofs_nbits); if (bundle->dst.n_bits < 16) { VLOG_WARN_RL(&rl, "bundle_load action requires at least 16 bit " "destination."); error = OFPERR_OFPBAC_BAD_ARGUMENT; } } if (slaves_size < bundle->n_slaves * sizeof(ovs_be16)) { VLOG_WARN_RL(&rl, "Nicira action %"PRIu16" only has %"PRIuSIZE" bytes " "allocated for slaves. %"PRIuSIZE" bytes are required for " "%"PRIu16" slaves.", subtype, slaves_size, bundle->n_slaves * sizeof(ovs_be16), bundle->n_slaves); error = OFPERR_OFPBAC_BAD_LEN; } for (i = 0; i < bundle->n_slaves; i++) { uint16_t ofp_port = ntohs(((ovs_be16 *)(nab + 1))[i]); ofpbuf_put(ofpacts, &ofp_port, sizeof ofp_port); } bundle = ofpacts->l2; ofpact_update_len(ofpacts, &bundle->ofpact); if (!error) { error = bundle_check(bundle, OFPP_MAX, NULL); } return error; }