Fix setting "of" device name based on unitialized dp_idx.
[sliver-openvswitch.git] / datapath / forward.c
index b3c2f7a..8b9b15a 100644 (file)
@@ -68,6 +68,8 @@ int run_flow_through_tables(struct sw_chain *chain, struct sk_buff *skb,
 void fwd_port_input(struct sw_chain *chain, struct sk_buff *skb,
                    struct net_bridge_port *p)
 {
+       WARN_ON_ONCE(skb_shared(skb));
+       WARN_ON_ONCE(skb->destructor);
        if (run_flow_through_tables(chain, skb, p))
                dp_output_control(chain->dp, skb, fwd_save_skb(skb), 
                                  chain->dp->miss_send_len,
@@ -120,8 +122,6 @@ recv_packet_out(struct sw_chain *chain, const struct sender *sender,
 {
        const struct ofp_packet_out *opo = msg;
        struct sk_buff *skb;
-       struct vlan_ethhdr *mac;
-       int nh_ofs;
        uint16_t v_code;
        struct sw_flow_key key;
        size_t actions_len = ntohs(opo->actions_len);
@@ -143,16 +143,11 @@ recv_packet_out(struct sw_chain *chain, const struct sender *sender,
                /* FIXME?  We don't reserve NET_IP_ALIGN or NET_SKB_PAD since
                 * we're just transmitting this raw without examining anything
                 * at those layers. */
-               memcpy(skb_put(skb, data_len), (uint8_t *)opo->actions + actions_len, 
-                               data_len);
-
-               skb_set_mac_header(skb, 0);
-               mac = vlan_eth_hdr(skb);
-               if (likely(mac->h_vlan_proto != htons(ETH_P_8021Q)))
-                       nh_ofs = sizeof(struct ethhdr);
-               else
-                       nh_ofs = sizeof(struct vlan_ethhdr);
-               skb_set_network_header(skb, nh_ofs);
+               skb_put(skb, data_len);
+               skb_copy_to_linear_data(skb,
+                                       (uint8_t *)opo->actions + actions_len, 
+                                       data_len);
+               skb_reset_mac_header(skb);
        } else {
                skb = retrieve_skb(ntohl(opo->buffer_id));
                if (!skb)
@@ -231,10 +226,11 @@ add_flow(struct sw_chain *chain, const struct sender *sender,
        flow->priority = flow->key.wildcards ? ntohs(ofm->priority) : -1;
        flow->idle_timeout = ntohs(ofm->idle_timeout);
        flow->hard_timeout = ntohs(ofm->hard_timeout);
-       flow->used = jiffies;
-       flow->init_time = jiffies;
+       flow->used = flow->created = get_jiffies_64();
        flow->byte_count = 0;
        flow->packet_count = 0;
+       flow->tcp_flags = 0;
+       flow->ip_tos = 0;
        spin_lock_init(&flow->lock);
        memcpy(flow->sf_acts->actions, ofm->actions, actions_len);
 
@@ -327,13 +323,14 @@ 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) ? 0 : -ESRCH;
+               return chain_delete(chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
        } else if (command == OFPFC_DELETE_STRICT) {
                struct sw_flow_key key;
                uint16_t priority;
                flow_extract_match(&key, &ofm->match);
                priority = key.wildcards ? ntohs(ofm->priority) : -1;
-               return chain_delete(chain, &key, priority, 1) ? 0 : -ESRCH;
+               return chain_delete(chain, &key, ofm->out_port, 
+                               priority, 1) ? 0 : -ESRCH;
        } else {
                return -ENOTSUPP;
        }
@@ -351,7 +348,7 @@ recv_vendor(struct sw_chain *chain, const struct sender *sender,
                return nx_recv_msg(chain, sender, msg);
        default:
                if (net_ratelimit())
-                       printk("Uknown vendor: %#x\n", ntohl(ovh->vendor));
+                       printk("unknown vendor: 0x%x\n", ntohl(ovh->vendor));
                dp_send_error_msg(chain->dp, sender, OFPET_BAD_REQUEST,
                                  OFPBRC_BAD_VENDOR, msg, ntohs(ovh->header.length));
                return -EINVAL;
@@ -470,6 +467,11 @@ uint32_t fwd_save_skb(struct sk_buff *skb)
        unsigned long int flags;
        uint32_t id;
 
+       /* FIXME: Probably just need a skb_clone() here. */
+       skb = skb_copy(skb, GFP_ATOMIC);
+       if (!skb)
+               return -1;
+
        spin_lock_irqsave(&buffer_lock, flags);
        buffer_idx = (buffer_idx + 1) & PKT_BUFFER_MASK;
        p = &buffers[buffer_idx];
@@ -478,9 +480,13 @@ uint32_t fwd_save_skb(struct sk_buff *skb)
                 * OVERWRITE_SECS old. */
                if (time_before(jiffies, p->exp_jiffies)) {
                        spin_unlock_irqrestore(&buffer_lock, flags);
+                       kfree_skb(skb);
                        return -1;
                } else {
-                       /* Defer kfree_skb() until interrupts re-enabled. */
+                       /* Defer kfree_skb() until interrupts re-enabled.
+                        * FIXME: we only need to do that if it has a
+                        * destructor, but it never should since we orphan
+                        * sk_buffs on entry. */
                        old_skb = p->skb;
                }
        }
@@ -488,7 +494,6 @@ uint32_t fwd_save_skb(struct sk_buff *skb)
         * special. */
        if (++p->cookie >= (1u << PKT_COOKIE_BITS) - 1)
                p->cookie = 0;
-       skb_get(skb);
        p->skb = skb;
        p->exp_jiffies = jiffies + OVERWRITE_JIFFIES;
        id = buffer_idx | (p->cookie << PKT_BUFFER_BITS);