X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Factions.c;h=5904c8312d4116464bb3c528f4d28c154e1acdf0;hb=2d8b103caa9fbd65f62c7727aa7ba4b3d0467a39;hp=18c4ea114882c81a07f2ecb72adddaf303d6cd2d;hpb=f1588b1fa1be46231ee079358e428dae74ff09cc;p=openvswitch diff --git a/datapath/actions.c b/datapath/actions.c index 18c4ea11..5904c831 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -25,13 +25,13 @@ #include "openvswitch/datapath-protocol.h" #include "vport.h" -static struct sk_buff *make_writable(struct sk_buff *skb, unsigned min_headroom, gfp_t gfp) +static struct sk_buff *make_writable(struct sk_buff *skb, unsigned min_headroom) { if (skb_cloned(skb)) { struct sk_buff *nskb; unsigned headroom = max(min_headroom, skb_headroom(skb)); - nskb = skb_copy_expand(skb, headroom, skb_tailroom(skb), gfp); + nskb = skb_copy_expand(skb, headroom, skb_tailroom(skb), GFP_ATOMIC); if (nskb) { set_skb_csum_bits(skb, nskb); kfree_skb(skb); @@ -72,20 +72,11 @@ 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, const struct odp_flow_key *key, - const union odp_action *a, int n_actions, - gfp_t gfp) + const union odp_action *a, int n_actions) { - u16 tci, mask; + __be16 tci = a->dl_tci.tci; - if (a->type == ODPAT_SET_VLAN_VID) { - tci = ntohs(a->vlan_vid.vlan_vid); - mask = VLAN_VID_MASK; - } else { - tci = a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT; - mask = VLAN_PCP_MASK; - } - - skb = make_writable(skb, VLAN_HLEN, gfp); + skb = make_writable(skb, VLAN_HLEN); if (!skb) return ERR_PTR(-ENOMEM); @@ -100,7 +91,7 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb, vh = vlan_eth_hdr(skb); old_tci = vh->h_vlan_TCI; - vh->h_vlan_TCI = htons((ntohs(vh->h_vlan_TCI) & ~mask) | tci); + vh->h_vlan_TCI = tci; if (OVS_CB(skb)->ip_summed == OVS_CSUM_COMPLETE) { __be16 diff[] = { ~old_tci, vh->h_vlan_TCI }; @@ -156,13 +147,12 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb, /* GSO can change the checksum type so update.*/ compute_ip_summed(segs, true); - segs = __vlan_put_tag(segs, tci); + segs = __vlan_put_tag(segs, ntohs(tci)); err = -ENOMEM; if (segs) { err = execute_actions(dp, segs, key, a + 1, - n_actions - 1, - gfp); + n_actions - 1); } if (unlikely(err)) { @@ -186,7 +176,7 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb, * e.g. vconfig(8)), so call the software-only version * __vlan_put_tag() directly instead. */ - skb = __vlan_put_tag(skb, tci); + skb = __vlan_put_tag(skb, ntohs(tci)); if (!skb) return ERR_PTR(-ENOMEM); @@ -200,20 +190,18 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb, return skb; } -static struct sk_buff *strip_vlan(struct sk_buff *skb, gfp_t gfp) +static struct sk_buff *strip_vlan(struct sk_buff *skb) { - skb = make_writable(skb, 0, gfp); + skb = make_writable(skb, 0); if (skb) vlan_pull_tag(skb); - return skb; } static struct sk_buff *set_dl_addr(struct sk_buff *skb, - const struct odp_action_dl_addr *a, - gfp_t gfp) + const struct odp_action_dl_addr *a) { - skb = make_writable(skb, 0, gfp); + skb = make_writable(skb, 0); if (skb) { struct ethhdr *eh = eth_hdr(skb); if (a->type == ODPAT_SET_DL_SRC) @@ -265,8 +253,7 @@ static __sum16 *get_l4_checksum(struct sk_buff *skb, const struct odp_flow_key * static struct sk_buff *set_nw_addr(struct sk_buff *skb, const struct odp_flow_key *key, - const struct odp_action_nw_addr *a, - gfp_t gfp) + const struct odp_action_nw_addr *a) { struct iphdr *nh; __sum16 *check; @@ -275,7 +262,7 @@ static struct sk_buff *set_nw_addr(struct sk_buff *skb, if (unlikely(!is_ip(skb, key))) return skb; - skb = make_writable(skb, 0, gfp); + skb = make_writable(skb, 0); if (unlikely(!skb)) return NULL; @@ -294,13 +281,12 @@ static struct sk_buff *set_nw_addr(struct sk_buff *skb, static struct sk_buff *set_nw_tos(struct sk_buff *skb, const struct odp_flow_key *key, - const struct odp_action_nw_tos *a, - gfp_t gfp) + const struct odp_action_nw_tos *a) { if (unlikely(!is_ip(skb, key))) return skb; - skb = make_writable(skb, 0, gfp); + skb = make_writable(skb, 0); if (skb) { struct iphdr *nh = ip_hdr(skb); u8 *f = &nh->tos; @@ -318,7 +304,7 @@ static struct sk_buff *set_nw_tos(struct sk_buff *skb, 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) { struct udphdr *th; __sum16 *check; @@ -327,7 +313,7 @@ static struct sk_buff *set_tp_port(struct sk_buff *skb, if (unlikely(!is_ip(skb, key))) return skb; - skb = make_writable(skb, 0, gfp); + skb = make_writable(skb, 0); if (unlikely(!skb)) return NULL; @@ -398,10 +384,9 @@ error: kfree_skb(skb); } -static int output_control(struct datapath *dp, struct sk_buff *skb, u32 arg, - gfp_t gfp) +static int output_control(struct datapath *dp, struct sk_buff *skb, u32 arg) { - skb = skb_clone(skb, gfp); + skb = skb_clone(skb, GFP_ATOMIC); if (!skb) return -ENOMEM; return dp_output_control(dp, skb, _ODPL_ACTION_NR, arg); @@ -411,14 +396,14 @@ static int output_control(struct datapath *dp, struct sk_buff *skb, u32 arg, * information about what happened to it. */ static void sflow_sample(struct datapath *dp, struct sk_buff *skb, const union odp_action *a, int n_actions, - gfp_t gfp, struct dp_port *dp_port) + struct dp_port *dp_port) { struct odp_sflow_sample_header *hdr; unsigned int actlen = n_actions * sizeof(union odp_action); unsigned int hdrlen = sizeof(struct odp_sflow_sample_header); struct sk_buff *nskb; - nskb = skb_copy_expand(skb, actlen + hdrlen, 0, gfp); + nskb = skb_copy_expand(skb, actlen + hdrlen, 0, GFP_ATOMIC); if (!nskb) return; @@ -432,8 +417,7 @@ static void sflow_sample(struct datapath *dp, struct sk_buff *skb, /* Execute a list of actions against 'skb'. */ int execute_actions(struct datapath *dp, struct sk_buff *skb, const struct odp_flow_key *key, - const union odp_action *a, int n_actions, - gfp_t gfp) + const union odp_action *a, int n_actions) { /* Every output action needs a separate clone of 'skb', but the common * case is just a single output action, so that doing a clone and @@ -449,7 +433,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb, atomic_inc(&p->sflow_pool); if (dp->sflow_probability == UINT_MAX || net_random() < dp->sflow_probability) - sflow_sample(dp, skb, a, n_actions, gfp, p); + sflow_sample(dp, skb, a, n_actions, p); } } @@ -457,7 +441,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb, for (; n_actions > 0; a++, n_actions--) { if (prev_port != -1) { - do_output(dp, skb_clone(skb, gfp), prev_port); + do_output(dp, skb_clone(skb, GFP_ATOMIC), prev_port); prev_port = -1; } @@ -467,7 +451,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb, break; case ODPAT_CONTROLLER: - err = output_control(dp, skb, a->controller.arg, gfp); + err = output_control(dp, skb, a->controller.arg); if (err) { kfree_skb(skb); return err; @@ -478,34 +462,33 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb, OVS_CB(skb)->tun_id = a->tunnel.tun_id; break; - case ODPAT_SET_VLAN_VID: - case ODPAT_SET_VLAN_PCP: - skb = modify_vlan_tci(dp, skb, key, a, n_actions, gfp); + case ODPAT_SET_DL_TCI: + skb = modify_vlan_tci(dp, skb, key, a, n_actions); if (IS_ERR(skb)) return PTR_ERR(skb); break; case ODPAT_STRIP_VLAN: - skb = strip_vlan(skb, gfp); + skb = strip_vlan(skb); break; case ODPAT_SET_DL_SRC: case ODPAT_SET_DL_DST: - skb = set_dl_addr(skb, &a->dl_addr, gfp); + skb = set_dl_addr(skb, &a->dl_addr); break; case ODPAT_SET_NW_SRC: case ODPAT_SET_NW_DST: - skb = set_nw_addr(skb, key, &a->nw_addr, gfp); + skb = set_nw_addr(skb, key, &a->nw_addr); break; case ODPAT_SET_NW_TOS: - skb = set_nw_tos(skb, key, &a->nw_tos, gfp); + skb = set_nw_tos(skb, key, &a->nw_tos); break; case ODPAT_SET_TP_SRC: case ODPAT_SET_TP_DST: - skb = set_tp_port(skb, key, &a->tp_port, gfp); + skb = set_tp_port(skb, key, &a->tp_port); break; case ODPAT_SET_PRIORITY: