From: Ben Pfaff Date: Thu, 1 Apr 2010 22:27:11 +0000 (-0700) Subject: flow: Separate "flow_t" from "struct odp_flow_key". X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=97ee114c3d3116174813e4c74d4a2adb92874862;p=sliver-openvswitch.git flow: Separate "flow_t" from "struct odp_flow_key". The "struct odp_flow_key" used in the kernel datapath is conceptually separate from the "flow_t" used in userspace, but until now we have used the latter as a typedef for the former for convenience. This commit separates them. This makes it possible in upcoming commits to change them independently. --- diff --git a/lib/classifier.c b/lib/classifier.c index ee78dadd9..d9345f6bd 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -58,7 +58,6 @@ void cls_rule_from_flow(struct cls_rule *rule, const flow_t *flow, uint32_t wildcards, unsigned int priority) { - assert(!flow->reserved[0] && !flow->reserved[1] && !flow->reserved[2]); rule->flow = *flow; flow_wildcards_init(&rule->wc, wildcards); rule->priority = priority; diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 1cc4ed46d..ab8910a11 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -95,14 +95,14 @@ 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 odp_flow_key key; /* Statistics. */ - struct timeval used; /* Last used time, in milliseconds. */ - long long int packet_count; /* Number of packets matched. */ - long long int byte_count; /* Number of bytes matched. */ - uint8_t ip_tos; /* IP TOS value. */ - uint16_t tcp_ctl; /* Bitwise-OR of seen tcp_ctl values. */ + struct timeval used; /* Last used time, in milliseconds. */ + long long int packet_count; /* Number of packets matched. */ + long long int byte_count; /* Number of bytes matched. */ + uint8_t ip_tos; /* IP TOS value. */ + uint16_t tcp_ctl; /* Bitwise-OR of seen tcp_ctl values. */ /* Actions. */ union odp_action *actions; @@ -137,7 +137,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 *, flow_t *, + struct ofpbuf *, struct odp_flow_key *, const union odp_action *, int n); static struct dpif_netdev * @@ -659,14 +659,14 @@ dpif_netdev_port_group_set(struct dpif *dpif, int group_no, } 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 odp_flow_key *key) { struct dp_netdev_flow *flow; - assert(!key->reserved[0] && !key->reserved[1] && !key->reserved[2]); HMAP_FOR_EACH_WITH_HASH (flow, struct dp_netdev_flow, node, - flow_hash(key, 0), &dp->flow_table) { - if (flow_equal(&flow->key, key)) { + odp_flow_key_hash(key, 0), &dp->flow_table) { + if (odp_flow_key_equal(&flow->key, key)) { return flow; } } @@ -812,7 +812,6 @@ add_flow(struct dpif *dpif, struct odp_flow *odp_flow) flow = xzalloc(sizeof *flow); flow->key = odp_flow->key; - memset(flow->key.reserved, 0, sizeof flow->key.reserved); error = set_flow_actions(flow, odp_flow); if (error) { @@ -820,7 +819,8 @@ add_flow(struct dpif *dpif, struct odp_flow *odp_flow) return error; } - hmap_insert(&dp->flow_table, &flow->node, flow_hash(&flow->key, 0)); + hmap_insert(&dp->flow_table, &flow->node, + odp_flow_key_hash(&flow->key, 0)); return 0; } @@ -907,6 +907,7 @@ dpif_netdev_execute(struct dpif *dpif, uint16_t in_port, struct dp_netdev *dp = get_dp_netdev(dpif); struct ofpbuf copy; bool mutates; + struct odp_flow_key key; flow_t flow; int error; @@ -933,7 +934,8 @@ dpif_netdev_execute(struct dpif *dpif, uint16_t in_port, copy = *packet; } flow_extract(©, in_port, &flow); - error = dp_netdev_execute_actions(dp, ©, &flow, actions, n_actions); + odp_flow_key_from_flow(&key, &flow); + error = dp_netdev_execute_actions(dp, ©, &key, actions, n_actions); if (mutates) { ofpbuf_uninit(©); } @@ -1002,7 +1004,8 @@ 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, + const struct odp_flow_key *key, const struct ofpbuf *packet) { time_timeval(&flow->used); @@ -1024,12 +1027,14 @@ 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 odp_flow_key key; + flow_t f; - if (flow_extract(packet, port->port_no, &key) && dp->drop_frags) { + if (flow_extract(packet, port->port_no, &f) && dp->drop_frags) { dp->n_frags++; return; } + odp_flow_key_from_flow(&key, &f); flow = dp_netdev_lookup_flow(dp, &key); if (flow) { @@ -1096,7 +1101,7 @@ dp_netdev_wait(void) * bits outside of 'mask'. */ static void -dp_netdev_modify_vlan_tci(struct ofpbuf *packet, flow_t *key, +dp_netdev_modify_vlan_tci(struct ofpbuf *packet, struct odp_flow_key *key, uint16_t tci, uint16_t mask) { struct vlan_eth_header *veh; @@ -1125,7 +1130,7 @@ dp_netdev_modify_vlan_tci(struct ofpbuf *packet, flow_t *key, } static void -dp_netdev_strip_vlan(struct ofpbuf *packet, flow_t *key) +dp_netdev_strip_vlan(struct ofpbuf *packet, struct odp_flow_key *key) { struct vlan_eth_header *veh = packet->l2; if (veh->veth_type == htons(ETH_TYPE_VLAN)) { @@ -1145,7 +1150,7 @@ dp_netdev_strip_vlan(struct ofpbuf *packet, flow_t *key) } static void -dp_netdev_set_dl_src(struct ofpbuf *packet, flow_t *key, +dp_netdev_set_dl_src(struct ofpbuf *packet, struct odp_flow_key *key, const uint8_t dl_addr[ETH_ADDR_LEN]) { struct eth_header *eh = packet->l2; @@ -1154,7 +1159,7 @@ dp_netdev_set_dl_src(struct ofpbuf *packet, flow_t *key, } static void -dp_netdev_set_dl_dst(struct ofpbuf *packet, flow_t *key, +dp_netdev_set_dl_dst(struct ofpbuf *packet, struct odp_flow_key *key, const uint8_t dl_addr[ETH_ADDR_LEN]) { struct eth_header *eh = packet->l2; @@ -1163,7 +1168,7 @@ dp_netdev_set_dl_dst(struct ofpbuf *packet, flow_t *key, } static void -dp_netdev_set_nw_addr(struct ofpbuf *packet, flow_t *key, +dp_netdev_set_nw_addr(struct ofpbuf *packet, struct odp_flow_key *key, const struct odp_action_nw_addr *a) { if (key->dl_type == htons(ETH_TYPE_IP)) { @@ -1195,7 +1200,7 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, flow_t *key, } static void -dp_netdev_set_nw_tos(struct ofpbuf *packet, flow_t *key, +dp_netdev_set_nw_tos(struct ofpbuf *packet, struct odp_flow_key *key, const struct odp_action_nw_tos *a) { if (key->dl_type == htons(ETH_TYPE_IP)) { @@ -1213,10 +1218,10 @@ dp_netdev_set_nw_tos(struct ofpbuf *packet, flow_t *key, } static void -dp_netdev_set_tp_port(struct ofpbuf *packet, flow_t *key, +dp_netdev_set_tp_port(struct ofpbuf *packet, struct odp_flow_key *key, const struct odp_action_tp_port *a) { - if (key->dl_type == htons(ETH_TYPE_IP)) { + if (key->dl_type == htons(ETH_TYPE_IP)) { uint16_t *field; if (key->nw_proto == IPPROTO_TCP) { struct tcp_header *th = packet->l4; @@ -1244,7 +1249,7 @@ static void dp_netdev_output_port(struct dp_netdev *dp, struct ofpbuf *packet, uint16_t out_port) { - struct dp_netdev_port *p = dp->ports[out_port]; + struct dp_netdev_port *p = dp->ports[out_port]; if (p) { netdev_send(p->netdev, packet); } @@ -1254,15 +1259,15 @@ static void dp_netdev_output_group(struct dp_netdev *dp, uint16_t group, uint16_t in_port, struct ofpbuf *packet) { - struct odp_port_group *g = &dp->groups[group]; - int i; + struct odp_port_group *g = &dp->groups[group]; + int i; - for (i = 0; i < g->n_ports; i++) { + for (i = 0; i < g->n_ports; i++) { uint16_t out_port = g->ports[i]; if (out_port != in_port) { dp_netdev_output_port(dp, packet, out_port); } - } + } } static int @@ -1294,66 +1299,66 @@ dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet, static int dp_netdev_execute_actions(struct dp_netdev *dp, - struct ofpbuf *packet, flow_t *key, + struct ofpbuf *packet, struct odp_flow_key *key, const union odp_action *actions, int n_actions) { int i; for (i = 0; i < n_actions; i++) { const union odp_action *a = &actions[i]; - switch (a->type) { - case ODPAT_OUTPUT: + switch (a->type) { + case ODPAT_OUTPUT: dp_netdev_output_port(dp, packet, a->output.port); - break; + break; - case ODPAT_OUTPUT_GROUP: - dp_netdev_output_group(dp, a->output_group.group, key->in_port, + case ODPAT_OUTPUT_GROUP: + dp_netdev_output_group(dp, a->output_group.group, key->in_port, packet); - break; + break; - case ODPAT_CONTROLLER: + case ODPAT_CONTROLLER: dp_netdev_output_control(dp, packet, _ODPL_ACTION_NR, key->in_port, a->controller.arg); - break; + break; - case ODPAT_SET_VLAN_VID: - dp_netdev_modify_vlan_tci(packet, key, ntohs(a->vlan_vid.vlan_vid), + case ODPAT_SET_VLAN_VID: + dp_netdev_modify_vlan_tci(packet, key, ntohs(a->vlan_vid.vlan_vid), VLAN_VID_MASK); - break; + break; - case ODPAT_SET_VLAN_PCP: - dp_netdev_modify_vlan_tci( - packet, key, a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT, - VLAN_PCP_MASK); - break; + case ODPAT_SET_VLAN_PCP: + dp_netdev_modify_vlan_tci( + packet, key, a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT, + VLAN_PCP_MASK); + break; - case ODPAT_STRIP_VLAN: - dp_netdev_strip_vlan(packet, key); - break; + case ODPAT_STRIP_VLAN: + dp_netdev_strip_vlan(packet, key); + break; - case ODPAT_SET_DL_SRC: + case ODPAT_SET_DL_SRC: dp_netdev_set_dl_src(packet, key, a->dl_addr.dl_addr); - break; + break; - case ODPAT_SET_DL_DST: + case ODPAT_SET_DL_DST: dp_netdev_set_dl_dst(packet, key, a->dl_addr.dl_addr); - break; - - case ODPAT_SET_NW_SRC: - case ODPAT_SET_NW_DST: - dp_netdev_set_nw_addr(packet, key, &a->nw_addr); - break; - - case ODPAT_SET_NW_TOS: - dp_netdev_set_nw_tos(packet, key, &a->nw_tos); - break; - - case ODPAT_SET_TP_SRC: - case ODPAT_SET_TP_DST: - dp_netdev_set_tp_port(packet, key, &a->tp_port); - break; - } - } + break; + + case ODPAT_SET_NW_SRC: + case ODPAT_SET_NW_DST: + dp_netdev_set_nw_addr(packet, key, &a->nw_addr); + break; + + case ODPAT_SET_NW_TOS: + dp_netdev_set_nw_tos(packet, key, &a->nw_tos); + break; + + case ODPAT_SET_TP_SRC: + case ODPAT_SET_TP_DST: + dp_netdev_set_tp_port(packet, key, &a->tp_port); + break; + } + } return 0; } diff --git a/lib/dpif.c b/lib/dpif.c index 315f11f9d..44d74b845 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1145,7 +1145,8 @@ should_log_flow_message(int error) static void log_flow_message(const struct dpif *dpif, int error, const char *operation, - const flow_t *flow, const struct odp_flow_stats *stats, + const struct odp_flow_key *flow, + const struct odp_flow_stats *stats, const union odp_action *actions, size_t n_actions) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -1157,7 +1158,7 @@ log_flow_message(const struct dpif *dpif, int error, const char *operation, if (error) { ds_put_format(&ds, "(%s) ", strerror(error)); } - flow_format(&ds, flow); + format_odp_flow_key(&ds, flow); if (stats) { ds_put_cstr(&ds, ", "); format_odp_flow_stats(&ds, stats); diff --git a/lib/flow.c b/lib/flow.c index 7d368bb6d..28aec66b4 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -280,7 +280,6 @@ flow_from_match(flow_t *flow, uint32_t *wildcards, memcpy(flow->dl_dst, match->dl_dst, ETH_ADDR_LEN); flow->nw_tos = match->nw_tos; flow->nw_proto = match->nw_proto; - memset(flow->reserved, 0, sizeof flow->reserved); } char * diff --git a/lib/flow.h b/lib/flow.h index ca140afaa..9eace0368 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -31,7 +31,29 @@ struct ds; struct ofp_match; struct ofpbuf; -typedef struct odp_flow_key flow_t; +typedef struct flow flow_t; +struct flow { + uint32_t nw_src; /* IP source address. */ + uint32_t nw_dst; /* IP destination address. */ + uint16_t in_port; /* Input switch port. */ + uint16_t dl_vlan; /* Input VLAN. */ + uint16_t dl_type; /* Ethernet frame type. */ + uint16_t tp_src; /* TCP/UDP source port. */ + uint16_t tp_dst; /* TCP/UDP destination port. */ + uint8_t dl_src[ETH_ALEN]; /* Ethernet source address. */ + uint8_t dl_dst[ETH_ALEN]; /* Ethernet destination address. */ + uint8_t nw_proto; /* IP protocol or low 8 bits of ARP opcode. */ + uint8_t dl_vlan_pcp; /* Input VLAN priority. */ + uint8_t nw_tos; /* IP ToS (DSCP field, 6 bits). */ +}; + +/* Assert that there are FLOW_SIG_SIZE bytes of significant data in "struct + * flow", followed by FLOW_PAD_SIZE bytes of padding. */ +#define FLOW_SIG_SIZE 33 +#define FLOW_PAD_SIZE 3 +BUILD_ASSERT_DECL(offsetof(struct flow, nw_tos) == FLOW_SIG_SIZE - 1); +BUILD_ASSERT_DECL(sizeof(((struct flow *)0)->nw_tos) == 1); +BUILD_ASSERT_DECL(sizeof(struct flow) == FLOW_SIG_SIZE + FLOW_PAD_SIZE); int flow_extract(struct ofpbuf *, uint16_t in_port, flow_t *); void flow_extract_stats(const flow_t *flow, struct ofpbuf *packet, @@ -48,7 +70,7 @@ static inline size_t flow_hash(const flow_t *, uint32_t basis); static inline int flow_compare(const flow_t *a, const flow_t *b) { - return memcmp(a, b, sizeof *a); + return memcmp(a, b, FLOW_SIG_SIZE); } static inline bool @@ -60,9 +82,7 @@ flow_equal(const flow_t *a, const flow_t *b) static inline size_t flow_hash(const flow_t *flow, uint32_t basis) { - BUILD_ASSERT_DECL(!(sizeof *flow % sizeof(uint32_t))); - return hash_words((const uint32_t *) flow, - sizeof *flow / sizeof(uint32_t), basis); + return hash_bytes(flow, FLOW_SIG_SIZE, basis); } /* Information on wildcards for a flow, as a supplement to flow_t. */ diff --git a/lib/odp-util.c b/lib/odp-util.c index 87ac92b82..09d067cca 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Nicira Networks. + * Copyright (c) 2009, 2010 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,19 @@ odp_actions_add(struct odp_actions *actions, uint16_t type) return a; } +void +format_odp_flow_key(struct ds *ds, const struct odp_flow_key *key) +{ + ds_put_format(ds, "in_port%04x:vlan%d:pcp%d mac"ETH_ADDR_FMT + "->"ETH_ADDR_FMT" type%04x proto%"PRId8" tos%"PRIu8 + " ip"IP_FMT"->"IP_FMT" port%d->%d", + key->in_port, ntohs(key->dl_vlan), key->dl_vlan_pcp, + ETH_ADDR_ARGS(key->dl_src), ETH_ADDR_ARGS(key->dl_dst), + ntohs(key->dl_type), key->nw_proto, key->nw_tos, + IP_ARGS(&key->nw_src), IP_ARGS(&key->nw_dst), + ntohs(key->tp_src), ntohs(key->tp_dst)); +} + void format_odp_action(struct ds *ds, const union odp_action *a) { @@ -128,10 +141,44 @@ format_odp_flow_stats(struct ds *ds, const struct odp_flow_stats *s) void format_odp_flow(struct ds *ds, const struct odp_flow *f) { - flow_format(ds, &f->key); + format_odp_flow_key(ds, &f->key); ds_put_cstr(ds, ", "); format_odp_flow_stats(ds, &f->stats); ds_put_cstr(ds, ", actions:"); format_odp_actions(ds, f->actions, f->n_actions); } + +void +odp_flow_key_from_flow(struct odp_flow_key *key, const struct flow *flow) +{ + key->nw_src = flow->nw_src; + key->nw_dst = flow->nw_dst; + key->in_port = flow->in_port; + key->dl_vlan = flow->dl_vlan; + key->dl_type = flow->dl_type; + key->tp_src = flow->tp_src; + key->tp_dst = flow->tp_dst; + memcpy(key->dl_src, flow->dl_src, ETH_ALEN); + memcpy(key->dl_dst, flow->dl_dst, ETH_ALEN); + key->nw_proto = flow->nw_proto; + key->dl_vlan_pcp = flow->dl_vlan_pcp; + key->nw_tos = flow->nw_tos; + memset(key->reserved, 0, sizeof key->reserved); +} +void +odp_flow_key_to_flow(const struct odp_flow_key *key, struct flow *flow) +{ + flow->nw_src = key->nw_src; + flow->nw_dst = key->nw_dst; + flow->in_port = key->in_port; + flow->dl_vlan = key->dl_vlan; + flow->dl_type = key->dl_type; + flow->tp_src = key->tp_src; + flow->tp_dst = key->tp_dst; + memcpy(flow->dl_src, key->dl_src, ETH_ALEN); + memcpy(flow->dl_dst, key->dl_dst, ETH_ALEN); + flow->nw_proto = key->nw_proto; + flow->dl_vlan_pcp = key->dl_vlan_pcp; + flow->nw_tos = key->nw_tos; +} diff --git a/lib/odp-util.h b/lib/odp-util.h index 6d67ec2cf..4c9cb91f0 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Nicira Networks. + * Copyright (c) 2009, 2010 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,13 @@ #include #include +#include +#include "hash.h" #include "openflow/openflow.h" #include "openvswitch/datapath-protocol.h" struct ds; +struct flow; /* The kernel datapaths limits actions to those that fit in a single page of * memory, so there is no point in allocating more than that. */ @@ -73,10 +76,28 @@ odp_port_to_ofp_port(uint16_t odp_port) } } +void format_odp_flow_key(struct ds *, const struct odp_flow_key *); void format_odp_action(struct ds *, const union odp_action *); void format_odp_actions(struct ds *, const union odp_action *actions, size_t n_actions); void format_odp_flow_stats(struct ds *, const struct odp_flow_stats *); void format_odp_flow(struct ds *, const struct odp_flow *); +void odp_flow_key_from_flow(struct odp_flow_key *, const struct flow *); +void odp_flow_key_to_flow(const struct odp_flow_key *, struct flow *); + +static inline bool +odp_flow_key_equal(const struct odp_flow_key *a, const struct odp_flow_key *b) +{ + return !memcmp(a, b, sizeof *a); +} + +static inline size_t +odp_flow_key_hash(const struct odp_flow_key *flow, uint32_t basis) +{ + BUILD_ASSERT_DECL(!(sizeof *flow % sizeof(uint32_t))); + return hash_words((const uint32_t *) flow, + sizeof *flow / sizeof(uint32_t), basis); +} + #endif /* odp-util.h */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 6976a0e1f..a9df90ef2 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1663,7 +1663,7 @@ do_put_flow(struct ofproto *ofproto, struct rule *rule, int flags, struct odp_flow_put *put) { memset(&put->flow.stats, 0, sizeof put->flow.stats); - put->flow.key = rule->cr.flow; + odp_flow_key_from_flow(&put->flow.key, &rule->cr.flow); put->flow.actions = rule->odp_actions; put->flow.n_actions = rule->n_odp_actions; put->flags = flags; @@ -1758,7 +1758,7 @@ rule_uninstall(struct ofproto *p, struct rule *rule) if (rule->installed) { struct odp_flow odp_flow; - odp_flow.key = rule->cr.flow; + odp_flow_key_from_flow(&odp_flow.key, &rule->cr.flow); odp_flow.actions = NULL; odp_flow.n_actions = 0; if (!dpif_flow_del(p->dpif, &odp_flow)) { @@ -2589,12 +2589,12 @@ query_stats(struct ofproto *p, struct rule *rule, if (rule->cr.wc.wildcards) { size_t i = 0; LIST_FOR_EACH (subrule, struct rule, list, &rule->list) { - odp_flows[i++].key = subrule->cr.flow; + odp_flow_key_from_flow(&odp_flows[i++].key, &subrule->cr.flow); packet_count += subrule->packet_count; byte_count += subrule->byte_count; } } else { - odp_flows[0].key = rule->cr.flow; + odp_flow_key_from_flow(&odp_flows[0].key, &rule->cr.flow); } /* Fetch up-to-date statistics from the datapath and add them in. */ @@ -3454,7 +3454,7 @@ active_timeout(struct ofproto *ofproto, struct rule *rule) /* Get updated flow stats. */ memset(&odp_flow, 0, sizeof odp_flow); if (rule->installed) { - odp_flow.key = rule->cr.flow; + odp_flow_key_from_flow(&odp_flow.key, &rule->cr.flow); odp_flow.flags = ODPFF_ZERO_TCP_FLAGS; dpif_flow_get(ofproto->dpif, &odp_flow); @@ -3495,9 +3495,12 @@ update_used(struct ofproto *p) for (i = 0; i < n_flows; i++) { struct odp_flow *f = &flows[i]; struct rule *rule; + flow_t flow; + + odp_flow_key_to_flow(&f->key, &flow); rule = rule_from_cls_rule( - classifier_find_rule_exactly(&p->cls, &f->key, 0, UINT16_MAX)); + classifier_find_rule_exactly(&p->cls, &flow, 0, UINT16_MAX)); if (!rule || !rule->installed) { COVERAGE_INC(ofproto_unexpected_rule); dpif_flow_del(p->dpif, f); diff --git a/tests/test-classifier.c b/tests/test-classifier.c index 563690dd0..3fb05b685 100644 --- a/tests/test-classifier.c +++ b/tests/test-classifier.c @@ -373,7 +373,6 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls) ETH_ADDR_LEN); flow.nw_proto = nw_proto_values[get_value(&x, N_NW_PROTO_VALUES)]; flow.nw_tos = nw_tos_values[get_value(&x, N_NW_TOS_VALUES)]; - memset(flow.reserved, 0, sizeof flow.reserved); for (include = 1; include <= 3; include++) { cr0 = lookup_with_include_bits(cls, &flow, include);