2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00

datapath: Don't update flow key when applying actions.

Currently the flow key is updated to match an action that is applied
to a packet but these field are never looked at again.  Not only is
this a waste of time it also makes optimizations involving caching
the flow key more difficult.
This commit is contained in:
Jesse Gross 2010-07-14 20:15:53 -07:00
parent 1cb8b59f8c
commit aebdcb93e0
3 changed files with 30 additions and 68 deletions

View File

@ -70,19 +70,18 @@ static struct sk_buff *vlan_pull_tag(struct sk_buff *skb)
} }
static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb, static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
struct odp_flow_key *key, const union odp_action *a, const struct odp_flow_key *key,
int n_actions, gfp_t gfp) const union odp_action *a, int n_actions,
gfp_t gfp)
{ {
u16 tci, mask; u16 tci, mask;
if (a->type == ODPAT_SET_VLAN_VID) { if (a->type == ODPAT_SET_VLAN_VID) {
tci = ntohs(a->vlan_vid.vlan_vid); tci = ntohs(a->vlan_vid.vlan_vid);
mask = VLAN_VID_MASK; mask = VLAN_VID_MASK;
key->dl_vlan = a->vlan_vid.vlan_vid;
} else { } else {
tci = a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT; tci = a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT;
mask = VLAN_PCP_MASK; mask = VLAN_PCP_MASK;
key->dl_vlan_pcp = a->vlan_pcp.vlan_pcp;
} }
skb = make_writable(skb, VLAN_HLEN, gfp); skb = make_writable(skb, VLAN_HLEN, gfp);
@ -153,9 +152,8 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
segs = __vlan_put_tag(segs, tci); segs = __vlan_put_tag(segs, tci);
err = -ENOMEM; err = -ENOMEM;
if (segs) { if (segs) {
struct odp_flow_key segkey = *key;
err = execute_actions(dp, segs, err = execute_actions(dp, segs,
&segkey, a + 1, key, a + 1,
n_actions - 1, n_actions - 1,
gfp); gfp);
} }
@ -195,32 +193,26 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
return skb; return skb;
} }
static struct sk_buff *strip_vlan(struct sk_buff *skb, static struct sk_buff *strip_vlan(struct sk_buff *skb, gfp_t gfp)
struct odp_flow_key *key, gfp_t gfp)
{ {
skb = make_writable(skb, 0, gfp); skb = make_writable(skb, 0, gfp);
if (skb) { if (skb)
vlan_pull_tag(skb); vlan_pull_tag(skb);
key->dl_vlan = htons(ODP_VLAN_NONE);
}
return skb; return skb;
} }
static struct sk_buff *set_dl_addr(struct sk_buff *skb, static struct sk_buff *set_dl_addr(struct sk_buff *skb,
struct odp_flow_key *key,
const struct odp_action_dl_addr *a, const struct odp_action_dl_addr *a,
gfp_t gfp) gfp_t gfp)
{ {
skb = make_writable(skb, 0, gfp); skb = make_writable(skb, 0, gfp);
if (skb) { if (skb) {
struct ethhdr *eh = eth_hdr(skb); struct ethhdr *eh = eth_hdr(skb);
if (a->type == ODPAT_SET_DL_SRC) { if (a->type == ODPAT_SET_DL_SRC)
memcpy(eh->h_source, a->dl_addr, ETH_ALEN); memcpy(eh->h_source, a->dl_addr, ETH_ALEN);
memcpy(key->dl_src, a->dl_addr, ETH_ALEN); else
} else {
memcpy(eh->h_dest, a->dl_addr, ETH_ALEN); memcpy(eh->h_dest, a->dl_addr, ETH_ALEN);
memcpy(key->dl_dst, a->dl_addr, ETH_ALEN);
}
} }
return skb; return skb;
} }
@ -246,7 +238,7 @@ static void update_csum(__sum16 *sum, struct sk_buff *skb,
} }
static struct sk_buff *set_nw_addr(struct sk_buff *skb, static struct sk_buff *set_nw_addr(struct sk_buff *skb,
struct odp_flow_key *key, const struct odp_flow_key *key,
const struct odp_action_nw_addr *a, const struct odp_action_nw_addr *a,
gfp_t gfp) gfp_t gfp)
{ {
@ -269,17 +261,12 @@ static struct sk_buff *set_nw_addr(struct sk_buff *skb,
} }
update_csum(&nh->check, skb, old, new, 0); update_csum(&nh->check, skb, old, new, 0);
*f = new; *f = new;
if (a->type == ODPAT_SET_NW_SRC)
key->nw_src = a->nw_addr;
else
key->nw_dst = a->nw_addr;
} }
return skb; return skb;
} }
static struct sk_buff *set_nw_tos(struct sk_buff *skb, static struct sk_buff *set_nw_tos(struct sk_buff *skb,
struct odp_flow_key *key, const struct odp_flow_key *key,
const struct odp_action_nw_tos *a, const struct odp_action_nw_tos *a,
gfp_t gfp) gfp_t gfp)
{ {
@ -298,12 +285,12 @@ static struct sk_buff *set_nw_tos(struct sk_buff *skb,
update_csum(&nh->check, skb, htons((uint16_t)old), update_csum(&nh->check, skb, htons((uint16_t)old),
htons((uint16_t)new), 0); htons((uint16_t)new), 0);
*f = new; *f = new;
key->nw_tos = a->nw_tos;
} }
return skb; return skb;
} }
static struct sk_buff *set_tp_port(struct sk_buff *skb, struct odp_flow_key *key, static struct sk_buff *set_tp_port(struct sk_buff *skb,
const struct odp_flow_key *key,
const struct odp_action_tp_port *a, gfp_t gfp) const struct odp_action_tp_port *a, gfp_t gfp)
{ {
int check_ofs; int check_ofs;
@ -327,10 +314,6 @@ static struct sk_buff *set_tp_port(struct sk_buff *skb, struct odp_flow_key *key
update_csum((u16*)(skb_transport_header(skb) + check_ofs), update_csum((u16*)(skb_transport_header(skb) + check_ofs),
skb, old, new, 0); skb, old, new, 0);
*f = new; *f = new;
if (a->type == ODPAT_SET_TP_SRC)
key->tp_src = a->tp_port;
else
key->tp_dst = a->tp_port;
} }
return skb; return skb;
} }
@ -412,7 +395,7 @@ static void sflow_sample(struct datapath *dp, struct sk_buff *skb,
/* Execute a list of actions against 'skb'. */ /* Execute a list of actions against 'skb'. */
int execute_actions(struct datapath *dp, struct sk_buff *skb, int execute_actions(struct datapath *dp, struct sk_buff *skb,
struct odp_flow_key *key, const struct odp_flow_key *key,
const union odp_action *a, int n_actions, const union odp_action *a, int n_actions,
gfp_t gfp) gfp_t gfp)
{ {
@ -462,7 +445,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
break; break;
case ODPAT_SET_TUNNEL: case ODPAT_SET_TUNNEL:
OVS_CB(skb)->tun_id = key->tun_id = a->tunnel.tun_id; OVS_CB(skb)->tun_id = a->tunnel.tun_id;
break; break;
case ODPAT_SET_VLAN_VID: case ODPAT_SET_VLAN_VID:
@ -473,12 +456,12 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
break; break;
case ODPAT_STRIP_VLAN: case ODPAT_STRIP_VLAN:
skb = strip_vlan(skb, key, gfp); skb = strip_vlan(skb, gfp);
break; break;
case ODPAT_SET_DL_SRC: case ODPAT_SET_DL_SRC:
case ODPAT_SET_DL_DST: case ODPAT_SET_DL_DST:
skb = set_dl_addr(skb, key, &a->dl_addr, gfp); skb = set_dl_addr(skb, &a->dl_addr, gfp);
break; break;
case ODPAT_SET_NW_SRC: case ODPAT_SET_NW_SRC:

View File

@ -18,7 +18,7 @@ struct odp_flow_key;
union odp_action; union odp_action;
int execute_actions(struct datapath *dp, struct sk_buff *skb, int execute_actions(struct datapath *dp, struct sk_buff *skb,
struct odp_flow_key *key, const struct odp_flow_key *key,
const union odp_action *, int n_actions, const union odp_action *, int n_actions,
gfp_t gfp); gfp_t gfp);

View File

@ -138,7 +138,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 *, static int dp_netdev_output_control(struct dp_netdev *, const struct ofpbuf *,
int queue_no, int port_no, uint32_t arg); int queue_no, int port_no, uint32_t arg);
static int dp_netdev_execute_actions(struct dp_netdev *, static int dp_netdev_execute_actions(struct dp_netdev *,
struct ofpbuf *, flow_t *, struct ofpbuf *, const flow_t *,
const union odp_action *, int n); const union odp_action *, int n);
static struct dpif_netdev * static struct dpif_netdev *
@ -1094,7 +1094,7 @@ dp_netdev_wait(void)
* bits outside of 'mask'. * bits outside of 'mask'.
*/ */
static void static void
dp_netdev_modify_vlan_tci(struct ofpbuf *packet, flow_t *key, dp_netdev_modify_vlan_tci(struct ofpbuf *packet, const flow_t *key,
uint16_t tci, uint16_t mask) uint16_t tci, uint16_t mask)
{ {
struct vlan_eth_header *veh; struct vlan_eth_header *veh;
@ -1118,12 +1118,10 @@ dp_netdev_modify_vlan_tci(struct ofpbuf *packet, flow_t *key,
memcpy(veh, &tmp, sizeof tmp); memcpy(veh, &tmp, sizeof tmp);
packet->l2 = (char*)packet->l2 - VLAN_HEADER_LEN; packet->l2 = (char*)packet->l2 - VLAN_HEADER_LEN;
} }
key->dl_vlan = veh->veth_tci & htons(VLAN_VID_MASK);
} }
static void static void
dp_netdev_strip_vlan(struct ofpbuf *packet, flow_t *key) dp_netdev_strip_vlan(struct ofpbuf *packet)
{ {
struct vlan_eth_header *veh = packet->l2; struct vlan_eth_header *veh = packet->l2;
if (veh->veth_type == htons(ETH_TYPE_VLAN)) { if (veh->veth_type == htons(ETH_TYPE_VLAN)) {
@ -1137,31 +1135,25 @@ dp_netdev_strip_vlan(struct ofpbuf *packet, flow_t *key)
packet->data = (char*)packet->data + VLAN_HEADER_LEN; packet->data = (char*)packet->data + VLAN_HEADER_LEN;
packet->l2 = (char*)packet->l2 + VLAN_HEADER_LEN; packet->l2 = (char*)packet->l2 + VLAN_HEADER_LEN;
memcpy(packet->data, &tmp, sizeof tmp); memcpy(packet->data, &tmp, sizeof tmp);
key->dl_vlan = htons(ODP_VLAN_NONE);
} }
} }
static void static void
dp_netdev_set_dl_src(struct ofpbuf *packet, flow_t *key, dp_netdev_set_dl_src(struct ofpbuf *packet, const uint8_t dl_addr[ETH_ADDR_LEN])
const uint8_t dl_addr[ETH_ADDR_LEN])
{ {
struct eth_header *eh = packet->l2; struct eth_header *eh = packet->l2;
memcpy(eh->eth_src, dl_addr, sizeof eh->eth_src); memcpy(eh->eth_src, dl_addr, sizeof eh->eth_src);
memcpy(key->dl_src, dl_addr, sizeof key->dl_src);
} }
static void static void
dp_netdev_set_dl_dst(struct ofpbuf *packet, flow_t *key, dp_netdev_set_dl_dst(struct ofpbuf *packet, const uint8_t dl_addr[ETH_ADDR_LEN])
const uint8_t dl_addr[ETH_ADDR_LEN])
{ {
struct eth_header *eh = packet->l2; struct eth_header *eh = packet->l2;
memcpy(eh->eth_dst, dl_addr, sizeof eh->eth_dst); memcpy(eh->eth_dst, dl_addr, sizeof eh->eth_dst);
memcpy(key->dl_dst, dl_addr, sizeof key->dl_dst);
} }
static void static void
dp_netdev_set_nw_addr(struct ofpbuf *packet, flow_t *key, dp_netdev_set_nw_addr(struct ofpbuf *packet, const flow_t *key,
const struct odp_action_nw_addr *a) const struct odp_action_nw_addr *a)
{ {
if (key->dl_type == htons(ETH_TYPE_IP)) { if (key->dl_type == htons(ETH_TYPE_IP)) {
@ -1183,17 +1175,11 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, flow_t *key,
} }
nh->ip_csum = recalc_csum32(nh->ip_csum, *field, a->nw_addr); nh->ip_csum = recalc_csum32(nh->ip_csum, *field, a->nw_addr);
*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;
}
} }
} }
static void static void
dp_netdev_set_nw_tos(struct ofpbuf *packet, flow_t *key, dp_netdev_set_nw_tos(struct ofpbuf *packet, const flow_t *key,
const struct odp_action_nw_tos *a) const struct odp_action_nw_tos *a)
{ {
if (key->dl_type == htons(ETH_TYPE_IP)) { if (key->dl_type == htons(ETH_TYPE_IP)) {
@ -1206,12 +1192,11 @@ dp_netdev_set_nw_tos(struct ofpbuf *packet, flow_t *key,
nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t)*field), nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t)*field),
htons((uint16_t)a->nw_tos)); htons((uint16_t)a->nw_tos));
*field = new; *field = new;
key->nw_tos = a->nw_tos;
} }
} }
static void static void
dp_netdev_set_tp_port(struct ofpbuf *packet, flow_t *key, dp_netdev_set_tp_port(struct ofpbuf *packet, const flow_t *key,
const struct odp_action_tp_port *a) const struct odp_action_tp_port *a)
{ {
if (key->dl_type == htons(ETH_TYPE_IP)) { if (key->dl_type == htons(ETH_TYPE_IP)) {
@ -1229,12 +1214,6 @@ dp_netdev_set_tp_port(struct ofpbuf *packet, flow_t *key,
} else { } else {
return; return;
} }
if (a->type == ODPAT_SET_TP_SRC) {
key->tp_src = a->tp_port;
} else {
key->tp_dst = a->tp_port;
}
} }
} }
@ -1293,7 +1272,7 @@ dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet,
static int static int
dp_netdev_execute_actions(struct dp_netdev *dp, dp_netdev_execute_actions(struct dp_netdev *dp,
struct ofpbuf *packet, flow_t *key, struct ofpbuf *packet, const flow_t *key,
const union odp_action *actions, int n_actions) const union odp_action *actions, int n_actions)
{ {
int i; int i;
@ -1327,15 +1306,15 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
break; break;
case ODPAT_STRIP_VLAN: case ODPAT_STRIP_VLAN:
dp_netdev_strip_vlan(packet, key); dp_netdev_strip_vlan(packet);
break; break;
case ODPAT_SET_DL_SRC: case ODPAT_SET_DL_SRC:
dp_netdev_set_dl_src(packet, key, a->dl_addr.dl_addr); dp_netdev_set_dl_src(packet, 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); dp_netdev_set_dl_dst(packet, a->dl_addr.dl_addr);
break; break;
case ODPAT_SET_NW_SRC: case ODPAT_SET_NW_SRC: