X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif-netdev.c;h=c4cc6e98357f594124f7ba14199da3f7a3c58c5b;hb=bfb1f2d5cbb9ef82f2def2f41f5ff8a8f02b5bbc;hp=e19cb34a272076c576b02674a1a0c37204a6cd39;hpb=2a910c50fad8f86b38d2f94f09e8f8e10c0ec7c8;p=openvswitch diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index e19cb34a..c4cc6e98 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -720,58 +721,64 @@ static int dpif_netdev_validate_actions(const union odp_action *actions, int n_actions, bool *mutates) { - unsigned int i; + unsigned int i; *mutates = false; - for (i = 0; i < n_actions; i++) { - const union odp_action *a = &actions[i]; - switch (a->type) { - case ODPAT_OUTPUT: - if (a->output.port >= MAX_PORTS) { - return EINVAL; + for (i = 0; i < n_actions; i++) { + const union odp_action *a = &actions[i]; + switch (a->type) { + case ODPAT_OUTPUT: + if (a->output.port >= MAX_PORTS) { + return EINVAL; } - break; + break; - case ODPAT_OUTPUT_GROUP: + case ODPAT_OUTPUT_GROUP: *mutates = true; - if (a->output_group.group >= N_GROUPS) { - return EINVAL; + if (a->output_group.group >= N_GROUPS) { + return EINVAL; } - break; + break; case ODPAT_CONTROLLER: break; - case ODPAT_SET_VLAN_VID: + case ODPAT_SET_VLAN_VID: *mutates = true; - if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK)) { - return EINVAL; + if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK)) { + return EINVAL; } - break; + break; - case ODPAT_SET_VLAN_PCP: + case ODPAT_SET_VLAN_PCP: *mutates = true; - if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) { - return EINVAL; + if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) { + return EINVAL; } - break; + break; + + case ODPAT_SET_NW_TOS: + *mutates = true; + if (a->nw_tos.nw_tos & IP_ECN_MASK) { + return EINVAL; + } + break; case ODPAT_STRIP_VLAN: case ODPAT_SET_DL_SRC: case ODPAT_SET_DL_DST: case ODPAT_SET_NW_SRC: case ODPAT_SET_NW_DST: - case ODPAT_SET_NW_TOS: case ODPAT_SET_TP_SRC: case ODPAT_SET_TP_DST: *mutates = true; break; - default: + default: return EOPNOTSUPP; - } - } - return 0; + } + } + return 0; } static int @@ -926,7 +933,7 @@ dpif_netdev_execute(struct dpif *dpif, uint16_t in_port, * if we don't. */ copy = *packet; } - flow_extract(©, in_port, &flow); + flow_extract(©, 0, in_port, &flow); error = dp_netdev_execute_actions(dp, ©, &flow, actions, n_actions); if (mutates) { ofpbuf_uninit(©); @@ -1020,7 +1027,7 @@ dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port, struct dp_netdev_flow *flow; flow_t key; - if (flow_extract(packet, port->port_no, &key) && dp->drop_frags) { + if (flow_extract(packet, 0, port->port_no, &key) && dp->drop_frags) { dp->n_frags++; return; } @@ -1139,19 +1146,21 @@ dp_netdev_strip_vlan(struct ofpbuf *packet, flow_t *key) } static void -dp_netdev_set_dl_src(struct ofpbuf *packet, +dp_netdev_set_dl_src(struct ofpbuf *packet, flow_t *key, const uint8_t dl_addr[ETH_ADDR_LEN]) { struct eth_header *eh = packet->l2; memcpy(eh->eth_src, dl_addr, sizeof eh->eth_src); + memcpy(key->dl_src, dl_addr, sizeof key->dl_src); } static void -dp_netdev_set_dl_dst(struct ofpbuf *packet, +dp_netdev_set_dl_dst(struct ofpbuf *packet, flow_t *key, const uint8_t dl_addr[ETH_ADDR_LEN]) { struct eth_header *eh = packet->l2; memcpy(eh->eth_dst, dl_addr, sizeof eh->eth_dst); + memcpy(key->dl_dst, dl_addr, sizeof key->dl_dst); } static void @@ -1177,6 +1186,12 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, flow_t *key, } nh->ip_csum = recalc_csum32(nh->ip_csum, *field, a->nw_addr); *field = a->nw_addr; + + if (a->type == ODPAT_SET_NW_SRC) { + key->nw_src = a->type; + } else { + key->nw_dst = a->type; + } } } @@ -1189,11 +1204,12 @@ dp_netdev_set_nw_tos(struct ofpbuf *packet, flow_t *key, uint8_t *field = &nh->ip_tos; /* Set the DSCP bits and preserve the ECN bits. */ - uint8_t new = (a->nw_tos & IP_DSCP_MASK) | (nh->ip_tos & IP_ECN_MASK); + uint8_t new = a->nw_tos | (nh->ip_tos & IP_ECN_MASK); nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t)*field), htons((uint16_t)a->nw_tos)); *field = new; + key->nw_tos = a->nw_tos; } } @@ -1213,6 +1229,14 @@ dp_netdev_set_tp_port(struct ofpbuf *packet, flow_t *key, field = a->type == ODPAT_SET_TP_SRC ? &uh->udp_src : &uh->udp_dst; uh->udp_csum = recalc_csum16(uh->udp_csum, *field, a->tp_port); *field = a->tp_port; + } else { + return; + } + + if (a->type == ODPAT_SET_TP_SRC) { + key->tp_src = a->tp_port; + } else { + key->tp_dst = a->tp_port; } } } @@ -1257,7 +1281,8 @@ dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet, } msg_size = sizeof *header + packet->size; - msg = ofpbuf_new(msg_size); + msg = ofpbuf_new(msg_size + DPIF_RECV_MSG_PADDING); + ofpbuf_reserve(msg, DPIF_RECV_MSG_PADDING); header = ofpbuf_put_uninit(msg, sizeof *header); header->type = queue_no; header->length = msg_size; @@ -1309,11 +1334,11 @@ dp_netdev_execute_actions(struct dp_netdev *dp, break; case ODPAT_SET_DL_SRC: - dp_netdev_set_dl_src(packet, a->dl_addr.dl_addr); + dp_netdev_set_dl_src(packet, key, a->dl_addr.dl_addr); break; case ODPAT_SET_DL_DST: - dp_netdev_set_dl_dst(packet, a->dl_addr.dl_addr); + dp_netdev_set_dl_dst(packet, key, a->dl_addr.dl_addr); break; case ODPAT_SET_NW_SRC: