X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif-linux.c;h=ad67ae76ae4178c534064b032b5294134c526bf7;hb=dd1ba5b3f4425c8eba008d1a93b044da63466812;hp=36e93cc3608af1519cb2aa7d488464ab5e979a5a;hpb=c2b565b54e36bc33d0406afb225c9bf3d01405ef;p=openvswitch diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index 36e93cc3..ad67ae76 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -59,10 +59,7 @@ #include "vlog.h" VLOG_DEFINE_THIS_MODULE(dpif_linux); - -enum { LRU_MAX_PORTS = 1024 }; -enum { LRU_MASK = LRU_MAX_PORTS - 1}; -BUILD_ASSERT_DECL(IS_POW2(LRU_MAX_PORTS)); +enum { MAX_PORTS = USHRT_MAX }; enum { N_UPCALL_SOCKS = 16 }; BUILD_ASSERT_DECL(IS_POW2(N_UPCALL_SOCKS)); @@ -147,11 +144,8 @@ struct dpif_linux { struct nln_notifier *port_notifier; bool change_error; - /* Queue of unused ports. */ - unsigned long *lru_bitmap; - uint16_t lru_ports[LRU_MAX_PORTS]; - size_t lru_head; - size_t lru_tail; + /* Port number allocation. */ + uint16_t alloc_port_no; }; static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5); @@ -184,29 +178,6 @@ dpif_linux_cast(const struct dpif *dpif) return CONTAINER_OF(dpif, struct dpif_linux, dpif); } -static void -dpif_linux_push_port(struct dpif_linux *dp, uint16_t port) -{ - if (port < LRU_MAX_PORTS && !bitmap_is_set(dp->lru_bitmap, port)) { - bitmap_set1(dp->lru_bitmap, port); - dp->lru_ports[dp->lru_head++ & LRU_MASK] = port; - } -} - -static uint32_t -dpif_linux_pop_port(struct dpif_linux *dp) -{ - uint16_t port; - - if (dp->lru_head == dp->lru_tail) { - return UINT32_MAX; - } - - port = dp->lru_ports[dp->lru_tail++ & LRU_MASK]; - bitmap_set0(dp->lru_bitmap, port); - return port; -} - static int dpif_linux_enumerate(struct sset *all_dps) { @@ -268,7 +239,6 @@ static void open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp) { struct dpif_linux *dpif; - int i; dpif = xzalloc(sizeof *dpif); dpif->port_notifier = nln_notifier_create(nln, dpif_linux_port_changed, @@ -281,12 +251,6 @@ open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp) dpif->dp_ifindex = dp->dp_ifindex; sset_init(&dpif->changed_ports); *dpifp = &dpif->dpif; - - dpif->lru_bitmap = bitmap_allocate(LRU_MAX_PORTS); - bitmap_set1(dpif->lru_bitmap, OVSP_LOCAL); - for (i = 1; i < LRU_MAX_PORTS; i++) { - dpif_linux_push_port(dpif, i); - } } static void @@ -312,7 +276,6 @@ dpif_linux_close(struct dpif *dpif_) nln_notifier_destroy(dpif->port_notifier); destroy_upcall_socks(dpif); sset_destroy(&dpif->changed_ports); - free(dpif->lru_bitmap); free(dpif); } @@ -372,7 +335,7 @@ dpif_linux_port_add(struct dpif *dpif_, struct netdev *netdev, struct dpif_linux_vport request, reply; const struct ofpbuf *options; struct ofpbuf *buf; - int error; + int error, i = 0, max_ports = MAX_PORTS; dpif_linux_vport_init(&request); request.cmd = OVS_VPORT_CMD_NEW; @@ -400,7 +363,7 @@ dpif_linux_port_add(struct dpif *dpif_, struct netdev *netdev, do { uint32_t upcall_pid; - request.port_no = dpif_linux_pop_port(dpif); + request.port_no = ++dpif->alloc_port_no; upcall_pid = dpif_linux_port_get_pid(dpif_, request.port_no); request.upcall_pid = &upcall_pid; error = dpif_linux_vport_transact(&request, &reply, &buf); @@ -409,9 +372,14 @@ dpif_linux_port_add(struct dpif *dpif_, struct netdev *netdev, *port_nop = reply.port_no; VLOG_DBG("%s: assigning port %"PRIu32" to netlink pid %"PRIu32, dpif_name(dpif_), request.port_no, upcall_pid); + } else if (error == EFBIG) { + /* Older datapath has lower limit. */ + max_ports = dpif->alloc_port_no; + dpif->alloc_port_no = 0; } + ofpbuf_delete(buf); - } while (request.port_no != UINT32_MAX + } while ((i++ < max_ports) && (error == EBUSY || error == EFBIG)); return error; @@ -430,9 +398,6 @@ dpif_linux_port_del(struct dpif *dpif_, uint16_t port_no) vport.port_no = port_no; error = dpif_linux_vport_transact(&vport, NULL, NULL); - if (!error) { - dpif_linux_push_port(dpif, port_no); - } return error; } @@ -478,9 +443,7 @@ dpif_linux_port_query_by_name(const struct dpif *dpif, const char *devname, static int dpif_linux_get_max_ports(const struct dpif *dpif OVS_UNUSED) { - /* If the datapath increases its range of supported ports, then it should - * start reporting that. */ - return 1024; + return MAX_PORTS; } static uint32_t @@ -510,8 +473,6 @@ dpif_linux_flow_flush(struct dpif *dpif_) struct dpif_linux_port_state { struct nl_dump dump; - unsigned long *port_bitmap; /* Ports in the datapath. */ - bool complete; /* Dump completed without error. */ }; static int @@ -523,8 +484,6 @@ dpif_linux_port_dump_start(const struct dpif *dpif_, void **statep) struct ofpbuf *buf; *statep = state = xmalloc(sizeof *state); - state->port_bitmap = bitmap_allocate(LRU_MAX_PORTS); - state->complete = false; dpif_linux_vport_init(&request); request.cmd = OVS_DP_CMD_GET; @@ -548,7 +507,6 @@ dpif_linux_port_dump_next(const struct dpif *dpif OVS_UNUSED, void *state_, int error; if (!nl_dump_next(&state->dump, &buf)) { - state->complete = true; return EOF; } @@ -557,10 +515,6 @@ dpif_linux_port_dump_next(const struct dpif *dpif OVS_UNUSED, void *state_, return error; } - if (vport.port_no < LRU_MAX_PORTS) { - bitmap_set1(state->port_bitmap, vport.port_no); - } - dpif_port->name = (char *) vport.name; dpif_port->type = (char *) netdev_vport_get_netdev_type(&vport); dpif_port->port_no = vport.port_no; @@ -568,23 +522,11 @@ dpif_linux_port_dump_next(const struct dpif *dpif OVS_UNUSED, void *state_, } static int -dpif_linux_port_dump_done(const struct dpif *dpif_, void *state_) +dpif_linux_port_dump_done(const struct dpif *dpif_ OVS_UNUSED, void *state_) { - struct dpif_linux *dpif = dpif_linux_cast(dpif_); struct dpif_linux_port_state *state = state_; int error = nl_dump_done(&state->dump); - if (state->complete) { - uint16_t i; - - for (i = 0; i < LRU_MAX_PORTS; i++) { - if (!bitmap_is_set(state->port_bitmap, i)) { - dpif_linux_push_port(dpif, i); - } - } - } - - free(state->port_bitmap); free(state); return error; } @@ -657,9 +599,7 @@ dpif_linux_flow_get(const struct dpif *dpif_, } static void -dpif_linux_init_flow_put(struct dpif *dpif_, enum dpif_flow_put_flags flags, - const struct nlattr *key, size_t key_len, - const struct nlattr *actions, size_t actions_len, +dpif_linux_init_flow_put(struct dpif *dpif_, const struct dpif_flow_put *put, struct dpif_linux_flow *request) { static struct nlattr dummy_action; @@ -667,37 +607,33 @@ dpif_linux_init_flow_put(struct dpif *dpif_, enum dpif_flow_put_flags flags, struct dpif_linux *dpif = dpif_linux_cast(dpif_); dpif_linux_flow_init(request); - request->cmd = (flags & DPIF_FP_CREATE + request->cmd = (put->flags & DPIF_FP_CREATE ? OVS_FLOW_CMD_NEW : OVS_FLOW_CMD_SET); request->dp_ifindex = dpif->dp_ifindex; - request->key = key; - request->key_len = key_len; + request->key = put->key; + request->key_len = put->key_len; /* Ensure that OVS_FLOW_ATTR_ACTIONS will always be included. */ - request->actions = actions ? actions : &dummy_action; - request->actions_len = actions_len; - if (flags & DPIF_FP_ZERO_STATS) { + request->actions = put->actions ? put->actions : &dummy_action; + request->actions_len = put->actions_len; + if (put->flags & DPIF_FP_ZERO_STATS) { request->clear = true; } - request->nlmsg_flags = flags & DPIF_FP_MODIFY ? 0 : NLM_F_CREATE; + request->nlmsg_flags = put->flags & DPIF_FP_MODIFY ? 0 : NLM_F_CREATE; } static int -dpif_linux_flow_put(struct dpif *dpif_, enum dpif_flow_put_flags flags, - const struct nlattr *key, size_t key_len, - const struct nlattr *actions, size_t actions_len, - struct dpif_flow_stats *stats) +dpif_linux_flow_put(struct dpif *dpif_, const struct dpif_flow_put *put) { struct dpif_linux_flow request, reply; struct ofpbuf *buf; int error; - dpif_linux_init_flow_put(dpif_, flags, key, key_len, actions, actions_len, - &request); + dpif_linux_init_flow_put(dpif_, put, &request); error = dpif_linux_flow_transact(&request, - stats ? &reply : NULL, - stats ? &buf : NULL); - if (!error && stats) { - dpif_linux_flow_get_stats(&reply, stats); + put->stats ? &reply : NULL, + put->stats ? &buf : NULL); + if (!error && put->stats) { + dpif_linux_flow_get_stats(&reply, put->stats); ofpbuf_delete(buf); } return error; @@ -821,39 +757,35 @@ dpif_linux_flow_dump_done(const struct dpif *dpif OVS_UNUSED, void *state_) static struct ofpbuf * dpif_linux_encode_execute(int dp_ifindex, - const struct nlattr *key, size_t key_len, - const struct nlattr *actions, size_t actions_len, - const struct ofpbuf *packet) + const struct dpif_execute *d_exec) { - struct ovs_header *execute; + struct ovs_header *k_exec; struct ofpbuf *buf; - buf = ofpbuf_new(128 + actions_len + packet->size); + buf = ofpbuf_new(128 + d_exec->actions_len + d_exec->packet->size); nl_msg_put_genlmsghdr(buf, 0, ovs_packet_family, NLM_F_REQUEST, OVS_PACKET_CMD_EXECUTE, OVS_PACKET_VERSION); - execute = ofpbuf_put_uninit(buf, sizeof *execute); - execute->dp_ifindex = dp_ifindex; + k_exec = ofpbuf_put_uninit(buf, sizeof *k_exec); + k_exec->dp_ifindex = dp_ifindex; - nl_msg_put_unspec(buf, OVS_PACKET_ATTR_PACKET, packet->data, packet->size); - nl_msg_put_unspec(buf, OVS_PACKET_ATTR_KEY, key, key_len); - nl_msg_put_unspec(buf, OVS_PACKET_ATTR_ACTIONS, actions, actions_len); + nl_msg_put_unspec(buf, OVS_PACKET_ATTR_PACKET, + d_exec->packet->data, d_exec->packet->size); + nl_msg_put_unspec(buf, OVS_PACKET_ATTR_KEY, d_exec->key, d_exec->key_len); + nl_msg_put_unspec(buf, OVS_PACKET_ATTR_ACTIONS, + d_exec->actions, d_exec->actions_len); return buf; } static int -dpif_linux_execute__(int dp_ifindex, const struct nlattr *key, size_t key_len, - const struct nlattr *actions, size_t actions_len, - const struct ofpbuf *packet) +dpif_linux_execute__(int dp_ifindex, const struct dpif_execute *execute) { struct ofpbuf *request; int error; - request = dpif_linux_encode_execute(dp_ifindex, - key, key_len, actions, actions_len, - packet); + request = dpif_linux_encode_execute(dp_ifindex, execute); error = nl_sock_transact(genl_sock, request, NULL); ofpbuf_delete(request); @@ -861,15 +793,11 @@ dpif_linux_execute__(int dp_ifindex, const struct nlattr *key, size_t key_len, } static int -dpif_linux_execute(struct dpif *dpif_, - const struct nlattr *key, size_t key_len, - const struct nlattr *actions, size_t actions_len, - const struct ofpbuf *packet) +dpif_linux_execute(struct dpif *dpif_, const struct dpif_execute *execute) { struct dpif_linux *dpif = dpif_linux_cast(dpif_); - return dpif_linux_execute__(dpif->dp_ifindex, key, key_len, - actions, actions_len, packet); + return dpif_linux_execute__(dpif->dp_ifindex, execute); } static void @@ -889,9 +817,7 @@ dpif_linux_operate(struct dpif *dpif_, struct dpif_op **ops, size_t n_ops) struct dpif_flow_put *put = &op->u.flow_put; struct dpif_linux_flow request; - dpif_linux_init_flow_put(dpif_, put->flags, put->key, put->key_len, - put->actions, put->actions_len, - &request); + dpif_linux_init_flow_put(dpif_, put, &request); if (put->stats) { request.nlmsg_flags |= NLM_F_ECHO; } @@ -900,9 +826,8 @@ dpif_linux_operate(struct dpif *dpif_, struct dpif_op **ops, size_t n_ops) } else if (op->type == DPIF_OP_EXECUTE) { struct dpif_execute *execute = &op->u.execute; - txn->request = dpif_linux_encode_execute( - dpif->dp_ifindex, execute->key, execute->key_len, - execute->actions, execute->actions_len, execute->packet); + txn->request = dpif_linux_encode_execute(dpif->dp_ifindex, + execute); } else { NOT_REACHED(); } @@ -1285,6 +1210,7 @@ dpif_linux_vport_send(int dp_ifindex, uint32_t port_no, { struct ofpbuf actions, key, packet; struct odputil_keybuf keybuf; + struct dpif_execute execute; struct flow flow; uint64_t action; @@ -1297,8 +1223,12 @@ dpif_linux_vport_send(int dp_ifindex, uint32_t port_no, ofpbuf_use_stack(&actions, &action, sizeof action); nl_msg_put_u32(&actions, OVS_ACTION_ATTR_OUTPUT, port_no); - return dpif_linux_execute__(dp_ifindex, key.data, key.size, - actions.data, actions.size, &packet); + execute.key = key.data; + execute.key_len = key.size; + execute.actions = actions.data; + execute.actions_len = actions.size; + execute.packet = &packet; + return dpif_linux_execute__(dp_ifindex, &execute); } static bool