X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif-netdev.c;h=aa4fdf830bf8cc7c14a3cf52c793c5553d26a4f6;hb=cb49ee4fd15e1b24aaae4a2d25f3dd538734b4df;hp=11ad370ff1da8965707fa3b726fc0950b8bd68d5;hpb=f1588b1fa1be46231ee079358e428dae74ff09cc;p=openvswitch diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 11ad370f..aa4fdf83 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -94,7 +94,7 @@ struct dp_netdev_port { /* A flow in dp_netdev's 'flow_table'. */ struct dp_netdev_flow { struct hmap_node node; /* Element in dp_netdev's 'flow_table'. */ - flow_t key; + struct flow key; /* Statistics. */ struct timespec used; /* Last used time. */ @@ -135,7 +135,7 @@ static int do_del_port(struct dp_netdev *, uint16_t port_no); static int dp_netdev_output_control(struct dp_netdev *, const struct ofpbuf *, int queue_no, int port_no, uint32_t arg); static int dp_netdev_execute_actions(struct dp_netdev *, - struct ofpbuf *, const flow_t *, + struct ofpbuf *, struct flow *, const union odp_action *, int n); static struct dpif_netdev * @@ -588,11 +588,10 @@ dpif_netdev_port_poll_wait(const struct dpif *dpif_) } static struct dp_netdev_flow * -dp_netdev_lookup_flow(const struct dp_netdev *dp, const flow_t *key) +dp_netdev_lookup_flow(const struct dp_netdev *dp, const struct flow *key) { struct dp_netdev_flow *flow; - assert(!key->reserved[0] && !key->reserved[1] && !key->reserved[2]); HMAP_FOR_EACH_WITH_HASH (flow, node, flow_hash(key, 0), &dp->flow_table) { if (flow_equal(&flow->key, key)) { return flow; @@ -601,12 +600,12 @@ dp_netdev_lookup_flow(const struct dp_netdev *dp, const flow_t *key) return NULL; } +/* The caller must fill in odp_flow->key itself. */ static void answer_flow_query(struct dp_netdev_flow *flow, uint32_t query_flags, struct odp_flow *odp_flow) { if (flow) { - odp_flow->key = flow->key; odp_flow->stats.n_packets = flow->packet_count; odp_flow->stats.n_bytes = flow->byte_count; odp_flow->stats.used_sec = flow->used.tv_sec; @@ -638,7 +637,10 @@ dpif_netdev_flow_get(const struct dpif *dpif, struct odp_flow flows[], int n) for (i = 0; i < n; i++) { struct odp_flow *odp_flow = &flows[i]; - answer_flow_query(dp_netdev_lookup_flow(dp, &odp_flow->key), + struct flow key; + + odp_flow_key_to_flow(&odp_flow->key, &key); + answer_flow_query(dp_netdev_lookup_flow(dp, &key), odp_flow->flags, odp_flow); } return 0; @@ -663,16 +665,14 @@ dpif_netdev_validate_actions(const union odp_action *actions, int n_actions, case ODPAT_CONTROLLER: break; - case ODPAT_SET_VLAN_VID: + case ODPAT_SET_DL_TCI: *mutates = true; - if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK)) { + if (a->dl_tci.mask != htons(VLAN_VID_MASK) + && a->dl_tci.mask != htons(VLAN_PCP_MASK) + && a->dl_tci.mask != htons(VLAN_VID_MASK | VLAN_PCP_MASK)) { return EINVAL; } - break; - - case ODPAT_SET_VLAN_PCP: - *mutates = true; - if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) { + if (a->dl_tci.tci & ~a->dl_tci.mask){ return EINVAL; } break; @@ -732,8 +732,7 @@ add_flow(struct dpif *dpif, struct odp_flow *odp_flow) int error; flow = xzalloc(sizeof *flow); - flow->key = odp_flow->key; - memset(flow->key.reserved, 0, sizeof flow->key.reserved); + odp_flow_key_to_flow(&odp_flow->key, &flow->key); error = set_flow_actions(flow, odp_flow); if (error) { @@ -760,8 +759,10 @@ dpif_netdev_flow_put(struct dpif *dpif, struct odp_flow_put *put) { struct dp_netdev *dp = get_dp_netdev(dpif); struct dp_netdev_flow *flow; + struct flow key; - flow = dp_netdev_lookup_flow(dp, &put->flow.key); + odp_flow_key_to_flow(&put->flow.key, &key); + flow = dp_netdev_lookup_flow(dp, &key); if (!flow) { if (put->flags & ODPPF_CREATE) { if (hmap_count(&dp->flow_table) < MAX_FLOWS) { @@ -791,8 +792,10 @@ dpif_netdev_flow_del(struct dpif *dpif, struct odp_flow *odp_flow) { struct dp_netdev *dp = get_dp_netdev(dpif); struct dp_netdev_flow *flow; + struct flow key; - flow = dp_netdev_lookup_flow(dp, &odp_flow->key); + odp_flow_key_to_flow(&odp_flow->key, &key); + flow = dp_netdev_lookup_flow(dp, &key); if (flow) { answer_flow_query(flow, 0, odp_flow); dp_netdev_free_flow(dp, flow); @@ -814,7 +817,10 @@ dpif_netdev_flow_list(const struct dpif *dpif, struct odp_flow flows[], int n) if (i >= n) { break; } - answer_flow_query(flow, 0, &flows[i++]); + + odp_flow_key_from_flow(&flows[i].key, &flow->key); + answer_flow_query(flow, 0, &flows[i]); + i++; } return hmap_count(&dp->flow_table); } @@ -827,7 +833,7 @@ dpif_netdev_execute(struct dpif *dpif, struct dp_netdev *dp = get_dp_netdev(dpif); struct ofpbuf copy; bool mutates; - flow_t flow; + struct flow key; int error; if (packet->size < ETH_HEADER_LEN || packet->size > UINT16_MAX) { @@ -852,8 +858,8 @@ dpif_netdev_execute(struct dpif *dpif, * if we don't. */ copy = *packet; } - flow_extract(©, 0, -1, &flow); - error = dp_netdev_execute_actions(dp, ©, &flow, actions, n_actions); + flow_extract(©, 0, -1, &key); + error = dp_netdev_execute_actions(dp, ©, &key, actions, n_actions); if (mutates) { ofpbuf_uninit(©); } @@ -922,7 +928,7 @@ dpif_netdev_recv_wait(struct dpif *dpif) } static void -dp_netdev_flow_used(struct dp_netdev_flow *flow, const flow_t *key, +dp_netdev_flow_used(struct dp_netdev_flow *flow, struct flow *key, const struct ofpbuf *packet) { time_timespec(&flow->used); @@ -939,7 +945,7 @@ dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port, struct ofpbuf *packet) { struct dp_netdev_flow *flow; - flow_t key; + struct flow key; if (packet->size < ETH_HEADER_LEN) { return; @@ -1005,16 +1011,16 @@ dp_netdev_wait(void) } -/* Modify the TCI field of 'packet'. If a VLAN tag is not present, one - * is added with the TCI field set to 'tci'. If a VLAN tag is present, - * then 'mask' bits are cleared before 'tci' is logically OR'd into the - * TCI field. +/* Modify the TCI field of 'packet'. If a VLAN tag is not present, one is + * added with the TCI field set to 'a->tci'. If a VLAN tag is present, then + * 'a->mask' bits are cleared before 'a->tci' is logically OR'd into the TCI + * field. * - * Note that the function does not ensure that 'tci' does not affect - * bits outside of 'mask'. + * Note that the function does not ensure that 'a->tci' does not affect bits + * outside of 'a->mask'. */ static void -dp_netdev_modify_vlan_tci(struct ofpbuf *packet, uint16_t tci, uint16_t mask) +dp_netdev_set_dl_tci(struct ofpbuf *packet, const struct odp_action_dl_tci *a) { struct vlan_eth_header *veh; struct eth_header *eh; @@ -1024,15 +1030,14 @@ dp_netdev_modify_vlan_tci(struct ofpbuf *packet, uint16_t tci, uint16_t mask) && eh->eth_type == htons(ETH_TYPE_VLAN)) { /* Clear 'mask' bits, but maintain other TCI bits. */ veh = packet->l2; - veh->veth_tci &= ~htons(mask); - veh->veth_tci |= htons(tci); + veh->veth_tci = (veh->veth_tci & ~a->mask) | a->tci; } else { /* Insert new 802.1Q header. */ struct vlan_eth_header tmp; memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN); memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN); tmp.veth_type = htons(ETH_TYPE_VLAN); - tmp.veth_tci = htons(tci); + tmp.veth_tci = htons(a->tci); tmp.veth_next_type = eh->eth_type; veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN); @@ -1075,13 +1080,13 @@ dp_netdev_set_dl_dst(struct ofpbuf *packet, const uint8_t dl_addr[ETH_ADDR_LEN]) } static bool -is_ip(const struct ofpbuf *packet, const flow_t *key) +is_ip(const struct ofpbuf *packet, const struct flow *key) { return key->dl_type == htons(ETH_TYPE_IP) && packet->l4; } static void -dp_netdev_set_nw_addr(struct ofpbuf *packet, const flow_t *key, +dp_netdev_set_nw_addr(struct ofpbuf *packet, struct flow *key, const struct odp_action_nw_addr *a) { if (is_ip(packet, key)) { @@ -1107,7 +1112,7 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, const flow_t *key, } static void -dp_netdev_set_nw_tos(struct ofpbuf *packet, const flow_t *key, +dp_netdev_set_nw_tos(struct ofpbuf *packet, struct flow *key, const struct odp_action_nw_tos *a) { if (is_ip(packet, key)) { @@ -1124,7 +1129,7 @@ dp_netdev_set_nw_tos(struct ofpbuf *packet, const flow_t *key, } static void -dp_netdev_set_tp_port(struct ofpbuf *packet, const flow_t *key, +dp_netdev_set_tp_port(struct ofpbuf *packet, struct flow *key, const struct odp_action_tp_port *a) { if (is_ip(packet, key)) { @@ -1186,7 +1191,7 @@ dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet, * screwy or truncated header fields or one whose inner and outer Ethernet * address differ. */ static bool -dp_netdev_is_spoofed_arp(struct ofpbuf *packet, const struct odp_flow_key *key) +dp_netdev_is_spoofed_arp(struct ofpbuf *packet, const struct flow *key) { struct arp_eth_header *arp; struct eth_header *eth; @@ -1212,7 +1217,7 @@ dp_netdev_is_spoofed_arp(struct ofpbuf *packet, const struct odp_flow_key *key) static int dp_netdev_execute_actions(struct dp_netdev *dp, - struct ofpbuf *packet, const flow_t *key, + struct ofpbuf *packet, struct flow *key, const union odp_action *actions, int n_actions) { int i; @@ -1229,15 +1234,8 @@ dp_netdev_execute_actions(struct dp_netdev *dp, key->in_port, a->controller.arg); break; - case ODPAT_SET_VLAN_VID: - dp_netdev_modify_vlan_tci(packet, ntohs(a->vlan_vid.vlan_vid), - VLAN_VID_MASK); - break; - - case ODPAT_SET_VLAN_PCP: - dp_netdev_modify_vlan_tci(packet, - a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT, - VLAN_PCP_MASK); + case ODPAT_SET_DL_TCI: + dp_netdev_set_dl_tci(packet, &a->dl_tci); break; case ODPAT_STRIP_VLAN: