Skip to content
Snippets Groups Projects
flow.c 54.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
    struct sw_flow_mask *ovs_sw_flow_mask_alloc(void)
    {
    	struct sw_flow_mask *mask;
    
    	mask = kmalloc(sizeof(*mask), GFP_KERNEL);
    	if (mask)
    		mask->ref_count = 0;
    
    	return mask;
    }
    
    void ovs_sw_flow_mask_add_ref(struct sw_flow_mask *mask)
    {
    	mask->ref_count++;
    }
    
    void ovs_sw_flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred)
    {
    	if (!mask)
    		return;
    
    	BUG_ON(!mask->ref_count);
    	mask->ref_count--;
    
    	if (!mask->ref_count) {
    		list_del_rcu(&mask->list);
    		if (deferred)
    			kfree_rcu(mask, rcu);
    		else
    			kfree(mask);
    	}
    }
    
    static bool ovs_sw_flow_mask_equal(const struct sw_flow_mask *a,
    		const struct sw_flow_mask *b)
    {
    	u8 *a_ = (u8 *)&a->key + a->range.start;
    	u8 *b_ = (u8 *)&b->key + b->range.start;
    
    	return  (a->range.end == b->range.end)
    		&& (a->range.start == b->range.start)
    
    		&& (memcmp(a_, b_, range_n_bytes(&a->range)) == 0);
    
    }
    
    struct sw_flow_mask *ovs_sw_flow_mask_find(const struct flow_table *tbl,
                                               const struct sw_flow_mask *mask)
    {
    	struct list_head *ml;
    
    	list_for_each(ml, tbl->mask_list) {
    		struct sw_flow_mask *m;
    		m = container_of(ml, struct sw_flow_mask, list);
    		if (ovs_sw_flow_mask_equal(mask, m))
    			return m;
    	}
    
    	return NULL;
    }
    
    /**
     * add a new mask into the mask list.
     * The caller needs to make sure that 'mask' is not the same
     * as any masks that are already on the list.
     */
    void ovs_sw_flow_mask_insert(struct flow_table *tbl, struct sw_flow_mask *mask)
    {
    	list_add_rcu(&mask->list, tbl->mask_list);
    }
    
    /**
     * Set 'range' fields in the mask to the value of 'val'.
     */
    static void ovs_sw_flow_mask_set(struct sw_flow_mask *mask,
    		struct sw_flow_key_range *range, u8 val)
    {
    	u8 *m = (u8 *)&mask->key + range->start;
    
    	mask->range = *range;
    
    	memset(m, val, range_n_bytes(range));