X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Fforward.c;h=c8df1a0a0b8037386495949ac0a58e53874d8323;hb=f2232335ab5089348f571462ab61ed7539e81354;hp=c1b70ca73e1e10dac86ddbea13b13a88f479e911;hpb=8623e6c16e7af939ed97e84b7e9b338215f04d49;p=sliver-openvswitch.git diff --git a/datapath/forward.c b/datapath/forward.c index c1b70ca73..c8df1a0a0 100644 --- a/datapath/forward.c +++ b/datapath/forward.c @@ -41,7 +41,7 @@ void fwd_port_input(struct sw_chain *chain, struct sk_buff *skb, int in_port) flow->actions, flow->n_actions); } else { dp_output_control(chain->dp, skb, fwd_save_skb(skb), - ntohs(chain->dp->config.miss_send_len), + chain->dp->miss_send_len, OFPR_NO_MATCH); } } @@ -87,10 +87,16 @@ void execute_actions(struct datapath *dp, struct sk_buff *skb, max_len = ntohs(a->arg.output.max_len); } else { if (!make_writable(&skb)) { - printk("make_writable failed\n"); + if (net_ratelimit()) + printk("make_writable failed\n"); break; } skb = execute_setter(skb, eth_proto, key, a); + if (!skb) { + if (net_ratelimit()) + printk("execute_setter lost skb\n"); + return; + } } } if (prev_port != -1) @@ -199,17 +205,23 @@ static struct sk_buff *vlan_pull_tag(struct sk_buff *skb) static struct sk_buff *modify_vlan(struct sk_buff *skb, const struct sw_flow_key *key, const struct ofp_action *a) { - uint16_t new_id = a->arg.vlan_id; + uint16_t new_id = ntohs(a->arg.vlan_id); if (new_id != OFP_VLAN_NONE) { if (key->dl_vlan != htons(OFP_VLAN_NONE)) { /* Modify vlan id, but maintain other TCI values */ struct vlan_ethhdr *vh = vlan_eth_hdr(skb); vh->h_vlan_TCI = (vh->h_vlan_TCI - & ~(htons(VLAN_VID_MASK))) | htons(new_id); + & ~(htons(VLAN_VID_MASK))) | a->arg.vlan_id; } else { /* Add vlan header */ - skb = vlan_put_tag(skb, new_id); + + /* xxx The vlan_put_tag function, doesn't seem to work + * xxx reliably when it attempts to use the hardware-accelerated + * xxx version. We'll directly use the software version + * xxx until the problem can be diagnosed. + */ + skb = __vlan_put_tag(skb, new_id); } } else { /* Remove an existing vlan header if it exists */ @@ -275,7 +287,10 @@ recv_set_config(struct sw_chain *chain, const struct sender *sender, const void *msg) { const struct ofp_switch_config *osc = msg; - chain->dp->config = *osc; + + chain->dp->flags = ntohs(osc->flags); + chain->dp->miss_send_len = ntohs(osc->miss_send_len); + return 0; } @@ -339,6 +354,20 @@ recv_port_mod(struct sw_chain *chain, const struct sender *sender, return 0; } +static int +recv_echo_request(struct sw_chain *chain, const struct sender *sender, + const void *msg) +{ + return dp_send_echo_reply(chain->dp, sender, msg); +} + +static int +recv_echo_reply(struct sw_chain *chain, const struct sender *sender, + const void *msg) +{ + return 0; +} + static int add_flow(struct sw_chain *chain, const struct ofp_flow_mod *ofm) { @@ -348,21 +377,16 @@ add_flow(struct sw_chain *chain, const struct ofp_flow_mod *ofm) struct sw_flow *flow; - /* Check number of actions. */ - n_acts = (ntohs(ofm->header.length) - sizeof *ofm) / sizeof *ofm->actions; - if (n_acts > MAX_ACTIONS) { - error = -E2BIG; - goto error; - } - /* To prevent loops, make sure there's no action to send to the * OFP_TABLE virtual port. */ + n_acts = (ntohs(ofm->header.length) - sizeof *ofm) / sizeof *ofm->actions; for (i=0; iactions[i]; if (a->type == htons(OFPAT_OUTPUT) - && a->arg.output.port == htons(OFPP_TABLE)) { + && (a->arg.output.port == htons(OFPP_TABLE) + || a->arg.output.port == htons(OFPP_NONE))) { /* xxx Send fancy new error message? */ goto error; } @@ -375,14 +399,13 @@ add_flow(struct sw_chain *chain, const struct ofp_flow_mod *ofm) /* Fill out flow. */ flow_extract_match(&flow->key, &ofm->match); - flow->group_id = ntohl(ofm->group_id); flow->max_idle = ntohs(ofm->max_idle); + flow->priority = flow->key.wildcards ? ntohs(ofm->priority) : -1; flow->timeout = jiffies + flow->max_idle * HZ; flow->n_actions = n_acts; flow->init_time = jiffies; flow->byte_count = 0; flow->packet_count = 0; - atomic_set(&flow->deleted, 0); spin_lock_init(&flow->lock); memcpy(flow->actions, ofm->actions, n_acts * sizeof *flow->actions); @@ -424,43 +447,18 @@ recv_flow(struct sw_chain *chain, const struct sender *sender, const void *msg) } else if (command == OFPFC_DELETE) { struct sw_flow_key key; flow_extract_match(&key, &ofm->match); - return chain_delete(chain, &key, 0) ? 0 : -ESRCH; + return chain_delete(chain, &key, 0, 0) ? 0 : -ESRCH; } else if (command == OFPFC_DELETE_STRICT) { struct sw_flow_key key; + uint16_t priority; flow_extract_match(&key, &ofm->match); - return chain_delete(chain, &key, 1) ? 0 : -ESRCH; - } else { - return -ENOTSUPP; - } -} - -static int -recv_flow_status_request(struct sw_chain *chain, const struct sender *sender, - const void *msg) -{ - const struct ofp_flow_stat_request *fsr = msg; - if (fsr->type == OFPFS_INDIV) { - return dp_send_flow_stats(chain->dp, sender, &fsr->match); + priority = key.wildcards ? ntohs(ofm->priority) : -1; + return chain_delete(chain, &key, priority, 1) ? 0 : -ESRCH; } else { - /* FIXME */ return -ENOTSUPP; } } -static int -recv_port_status_request(struct sw_chain *chain, const struct sender *sender, - const void *msg) -{ - return dp_send_port_stats(chain->dp, sender); -} - -static int -recv_table_status_request(struct sw_chain *chain, const struct sender *sender, - const void *msg) -{ - return dp_send_table_stats(chain->dp, sender); -} - /* 'msg', which is 'length' bytes long, was received across Netlink from * 'sender'. Apply it to 'chain'. */ int @@ -499,17 +497,13 @@ fwd_control_input(struct sw_chain *chain, const struct sender *sender, sizeof (struct ofp_port_mod), recv_port_mod, }, - [OFPT_FLOW_STAT_REQUEST] = { - sizeof (struct ofp_flow_stat_request), - recv_flow_status_request, - }, - [OFPT_PORT_STAT_REQUEST] = { - sizeof (struct ofp_port_stat_request), - recv_port_status_request, + [OFPT_ECHO_REQUEST] = { + sizeof (struct ofp_header), + recv_echo_request, }, - [OFPT_TABLE_STAT_REQUEST] = { - sizeof (struct ofp_table_stat_request), - recv_table_status_request, + [OFPT_ECHO_REPLY] = { + sizeof (struct ofp_header), + recv_echo_reply, }, }; @@ -596,6 +590,19 @@ static struct sk_buff *retrieve_skb(uint32_t id) return skb; } +void fwd_discard_all(void) +{ + unsigned long int flags; + int i; + + spin_lock_irqsave(&buffer_lock, flags); + for (i = 0; i < N_PKT_BUFFERS; i++) { + kfree_skb(buffers[i].skb); + buffers[i].skb = NULL; + } + spin_unlock_irqrestore(&buffer_lock, flags); +} + static void discard_skb(uint32_t id) { unsigned long int flags; @@ -612,10 +619,7 @@ static void discard_skb(uint32_t id) void fwd_exit(void) { - int i; - - for (i = 0; i < N_PKT_BUFFERS; i++) - kfree_skb(buffers[i].skb); + fwd_discard_all(); } /* Utility functions. */ @@ -633,7 +637,7 @@ make_writable(struct sk_buff **pskb) if (skb_shared(*pskb) || skb_cloned(*pskb)) goto copy_skb; - return pskb_may_pull(*pskb, 64); /* FIXME? */ + return pskb_may_pull(*pskb, 40); /* FIXME? */ copy_skb: nskb = skb_copy(*pskb, GFP_ATOMIC);