X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif-linux.c;h=509174c869d1ce18b5ad9fd759374450742677f1;hb=e868fb3d322f5c46385f1fc6db5bb1ab33f90305;hp=f08a2589320ded113010b36889a09194074ccf69;hpb=3d8c95357fc8fa657c5ed176a464d0c9d33622e9;p=openvswitch diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index f08a2589..509174c8 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -89,7 +89,10 @@ struct dpif_linux_flow { * * The 'stats' and 'used' members point to 64-bit data that might only be * aligned on 32-bit boundaries, so get_unaligned_u64() should be used to - * access their values. */ + * access their values. + * + * If 'actions' is nonnull then ODP_FLOW_ATTR_ACTIONS will be included in + * the Netlink version of the command, even if actions_len is zero. */ const struct nlattr *key; /* ODP_FLOW_ATTR_KEY. */ size_t key_len; const struct nlattr *actions; /* ODP_FLOW_ATTR_ACTIONS. */ @@ -209,7 +212,6 @@ static int open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp) { struct dpif_linux *dpif; - char *name; int error; int i; @@ -222,7 +224,6 @@ open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp) dpif_init(&dpif->dpif, &dpif_linux_class, dp->name, dp->dp_ifindex, dp->dp_ifindex); - free(name); dpif->mc_sock = NULL; for (i = 0; i < DPIF_N_UC_TYPES; i++) { @@ -505,21 +506,31 @@ dpif_linux_port_poll_wait(const struct dpif *dpif_) } static int -dpif_linux_flow_get(const struct dpif *dpif_, - const struct nlattr *key, size_t key_len, - struct ofpbuf **actionsp, struct dpif_flow_stats *stats) +dpif_linux_flow_get__(const struct dpif *dpif_, + const struct nlattr *key, size_t key_len, + struct dpif_linux_flow *reply, struct ofpbuf **bufp) { struct dpif_linux *dpif = dpif_linux_cast(dpif_); - struct dpif_linux_flow request, reply; - struct ofpbuf *buf; - int error; + struct dpif_linux_flow request; dpif_linux_flow_init(&request); request.cmd = ODP_FLOW_CMD_GET; request.dp_ifindex = dpif->dp_ifindex; request.key = key; request.key_len = key_len; - error = dpif_linux_flow_transact(&request, &reply, &buf); + return dpif_linux_flow_transact(&request, reply, bufp); +} + +static int +dpif_linux_flow_get(const struct dpif *dpif_, + const struct nlattr *key, size_t key_len, + struct ofpbuf **actionsp, struct dpif_flow_stats *stats) +{ + struct dpif_linux_flow reply; + struct ofpbuf *buf; + int error; + + error = dpif_linux_flow_get__(dpif_, key, key_len, &reply, &buf); if (!error) { if (stats) { dpif_linux_flow_get_stats(&reply, stats); @@ -543,6 +554,7 @@ dpif_linux_flow_put(struct dpif *dpif_, enum dpif_flow_put_flags flags, { struct dpif_linux *dpif = dpif_linux_cast(dpif_); struct dpif_linux_flow request, reply; + struct nlattr dummy_action; struct ofpbuf *buf; int error; @@ -551,7 +563,8 @@ dpif_linux_flow_put(struct dpif *dpif_, enum dpif_flow_put_flags flags, request.dp_ifindex = dpif->dp_ifindex; request.key = key; request.key_len = key_len; - request.actions = actions; + /* Ensure that ODP_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.clear = true; @@ -596,6 +609,7 @@ struct dpif_linux_flow_state { struct nl_dump dump; struct dpif_linux_flow flow; struct dpif_flow_stats stats; + struct ofpbuf *buf; }; static int @@ -617,6 +631,8 @@ dpif_linux_flow_dump_start(const struct dpif *dpif_, void **statep) nl_dump_start(&state->dump, genl_sock, buf); ofpbuf_delete(buf); + state->buf = NULL; + return 0; } @@ -630,24 +646,42 @@ dpif_linux_flow_dump_next(const struct dpif *dpif_ OVS_UNUSED, void *state_, struct ofpbuf buf; int error; - if (!nl_dump_next(&state->dump, &buf)) { - return EOF; - } + do { + ofpbuf_delete(state->buf); + state->buf = NULL; - error = dpif_linux_flow_from_ofpbuf(&state->flow, &buf); - if (!error) { - if (key) { - *key = state->flow.key; - *key_len = state->flow.key_len; + if (!nl_dump_next(&state->dump, &buf)) { + return EOF; } - if (actions) { - *actions = state->flow.actions; - *actions_len = state->flow.actions_len; + + error = dpif_linux_flow_from_ofpbuf(&state->flow, &buf); + if (error) { + return error; } - if (stats) { - dpif_linux_flow_get_stats(&state->flow, &state->stats); - *stats = &state->stats; + + if (actions && !state->flow.actions) { + error = dpif_linux_flow_get__(dpif_, state->flow.key, + state->flow.key_len, + &state->flow, &state->buf); + if (error == ENOENT) { + VLOG_DBG("dumped flow disappeared on get"); + } else if (error) { + VLOG_WARN("error fetching dumped flow: %s", strerror(error)); + } } + } while (error); + + if (actions) { + *actions = state->flow.actions; + *actions_len = state->flow.actions_len; + } + if (key) { + *key = state->flow.key; + *key_len = state->flow.key_len; + } + if (stats) { + dpif_linux_flow_get_stats(&state->flow, &state->stats); + *stats = &state->stats; } return error; } @@ -657,6 +691,7 @@ dpif_linux_flow_dump_done(const struct dpif *dpif OVS_UNUSED, void *state_) { struct dpif_linux_flow_state *state = state_; int error = nl_dump_done(&state->dump); + ofpbuf_delete(state->buf); free(state); return error; } @@ -1073,6 +1108,8 @@ dpif_linux_vport_from_ofpbuf(struct dpif_linux_vport *vport, } if (a[ODP_VPORT_ATTR_MTU]) { vport->mtu = nl_attr_get_u32(a[ODP_VPORT_ATTR_MTU]); + } else { + vport->mtu = INT_MAX; } if (a[ODP_VPORT_ATTR_OPTIONS]) { vport->options = nl_attr_get(a[ODP_VPORT_ATTR_OPTIONS]); @@ -1123,7 +1160,7 @@ dpif_linux_vport_to_ofpbuf(const struct dpif_linux_vport *vport, vport->address, ETH_ADDR_LEN); } - if (vport->mtu) { + if (vport->mtu && vport->mtu != INT_MAX) { nl_msg_put_u32(buf, ODP_VPORT_ATTR_MTU, vport->mtu); } @@ -1439,6 +1476,9 @@ dpif_linux_flow_from_ofpbuf(struct dpif_linux_flow *flow, if (a[ODP_FLOW_ATTR_TCP_FLAGS]) { flow->tcp_flags = nl_attr_get(a[ODP_FLOW_ATTR_TCP_FLAGS]); } + if (a[ODP_FLOW_ATTR_USED]) { + flow->used = nl_attr_get(a[ODP_FLOW_ATTR_USED]); + } return 0; } @@ -1451,7 +1491,8 @@ dpif_linux_flow_to_ofpbuf(const struct dpif_linux_flow *flow, struct odp_header *odp_header; nl_msg_put_genlmsghdr(buf, 0, odp_flow_family, - NLM_F_REQUEST | flow->nlmsg_flags, flow->cmd, 1); + NLM_F_REQUEST | NLM_F_ECHO | flow->nlmsg_flags, + flow->cmd, 1); odp_header = ofpbuf_put_uninit(buf, sizeof *odp_header); odp_header->dp_ifindex = flow->dp_ifindex; @@ -1460,7 +1501,7 @@ dpif_linux_flow_to_ofpbuf(const struct dpif_linux_flow *flow, nl_msg_put_unspec(buf, ODP_FLOW_ATTR_KEY, flow->key, flow->key_len); } - if (flow->actions_len) { + if (flow->actions || flow->actions_len) { nl_msg_put_unspec(buf, ODP_FLOW_ATTR_ACTIONS, flow->actions, flow->actions_len); }