2011-10-26 06:26:31 +04:00
/*
2014-09-16 06:37:25 +04:00
* Copyright ( c ) 2007 - 2014 Nicira , Inc .
2011-10-26 06:26:31 +04:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 , USA
*/
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
# include <linux/skbuff.h>
# include <linux/in.h>
# include <linux/ip.h>
# include <linux/openvswitch.h>
2015-08-26 21:31:48 +03:00
# include <linux/netfilter_ipv6.h>
2013-08-22 23:30:48 +04:00
# include <linux/sctp.h>
2011-10-26 06:26:31 +04:00
# include <linux/tcp.h>
# include <linux/udp.h>
# include <linux/in6.h>
# include <linux/if_arp.h>
# include <linux/if_vlan.h>
2014-10-06 16:05:13 +04:00
2015-08-26 21:31:48 +03:00
# include <net/dst.h>
2011-10-26 06:26:31 +04:00
# include <net/ip.h>
2012-11-14 03:44:14 +04:00
# include <net/ipv6.h>
2015-08-28 01:25:46 +03:00
# include <net/ip6_fib.h>
2011-10-26 06:26:31 +04:00
# include <net/checksum.h>
# include <net/dsfield.h>
2014-10-06 16:05:13 +04:00
# include <net/mpls.h>
2013-08-22 23:30:48 +04:00
# include <net/sctp/checksum.h>
2011-10-26 06:26:31 +04:00
# include "datapath.h"
2014-09-16 06:37:25 +04:00
# include "flow.h"
2015-08-26 21:31:48 +03:00
# include "conntrack.h"
2011-10-26 06:26:31 +04:00
# include "vport.h"
static int do_execute_actions ( struct datapath * dp , struct sk_buff * skb ,
2014-09-16 06:15:28 +04:00
struct sw_flow_key * key ,
2014-07-22 02:12:34 +04:00
const struct nlattr * attr , int len ) ;
2011-10-26 06:26:31 +04:00
2014-09-16 06:37:25 +04:00
struct deferred_action {
struct sk_buff * skb ;
const struct nlattr * actions ;
/* Store pkt_key clone when creating deferred action. */
struct sw_flow_key pkt_key ;
} ;
2015-08-26 21:31:48 +03:00
# define MAX_L2_LEN (VLAN_ETH_HLEN + 3 * MPLS_HLEN)
struct ovs_frag_data {
unsigned long dst ;
struct vport * vport ;
struct ovs_skb_cb cb ;
__be16 inner_protocol ;
__u16 vlan_tci ;
__be16 vlan_proto ;
unsigned int l2_len ;
u8 l2_data [ MAX_L2_LEN ] ;
} ;
static DEFINE_PER_CPU ( struct ovs_frag_data , ovs_frag_data_storage ) ;
2014-09-16 06:37:25 +04:00
# define DEFERRED_ACTION_FIFO_SIZE 10
struct action_fifo {
int head ;
int tail ;
/* Deferred action fifo queue storage. */
struct deferred_action fifo [ DEFERRED_ACTION_FIFO_SIZE ] ;
} ;
static struct action_fifo __percpu * action_fifos ;
static DEFINE_PER_CPU ( int , exec_actions_level ) ;
static void action_fifo_init ( struct action_fifo * fifo )
{
fifo - > head = 0 ;
fifo - > tail = 0 ;
}
2014-11-06 17:58:52 +03:00
static bool action_fifo_is_empty ( const struct action_fifo * fifo )
2014-09-16 06:37:25 +04:00
{
return ( fifo - > head = = fifo - > tail ) ;
}
static struct deferred_action * action_fifo_get ( struct action_fifo * fifo )
{
if ( action_fifo_is_empty ( fifo ) )
return NULL ;
return & fifo - > fifo [ fifo - > tail + + ] ;
}
static struct deferred_action * action_fifo_put ( struct action_fifo * fifo )
{
if ( fifo - > head > = DEFERRED_ACTION_FIFO_SIZE - 1 )
return NULL ;
return & fifo - > fifo [ fifo - > head + + ] ;
}
/* Return true if fifo is not full */
static struct deferred_action * add_deferred_actions ( struct sk_buff * skb ,
2014-11-06 17:58:52 +03:00
const struct sw_flow_key * key ,
2014-09-16 06:37:25 +04:00
const struct nlattr * attr )
{
struct action_fifo * fifo ;
struct deferred_action * da ;
fifo = this_cpu_ptr ( action_fifos ) ;
da = action_fifo_put ( fifo ) ;
if ( da ) {
da - > skb = skb ;
da - > actions = attr ;
da - > pkt_key = * key ;
}
return da ;
}
2014-11-06 17:55:14 +03:00
static void invalidate_flow_key ( struct sw_flow_key * key )
{
key - > eth . type = htons ( 0 ) ;
}
static bool is_flow_key_valid ( const struct sw_flow_key * key )
{
return ! ! key - > eth . type ;
}
static int push_mpls ( struct sk_buff * skb , struct sw_flow_key * key ,
2014-10-06 16:05:13 +04:00
const struct ovs_action_push_mpls * mpls )
{
__be32 * new_mpls_lse ;
struct ethhdr * hdr ;
/* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */
if ( skb - > encapsulation )
return - ENOTSUPP ;
if ( skb_cow_head ( skb , MPLS_HLEN ) < 0 )
return - ENOMEM ;
skb_push ( skb , MPLS_HLEN ) ;
memmove ( skb_mac_header ( skb ) - MPLS_HLEN , skb_mac_header ( skb ) ,
skb - > mac_len ) ;
skb_reset_mac_header ( skb ) ;
new_mpls_lse = ( __be32 * ) skb_mpls_header ( skb ) ;
* new_mpls_lse = mpls - > mpls_lse ;
2016-02-20 02:29:30 +03:00
skb_postpush_rcsum ( skb , new_mpls_lse , MPLS_HLEN ) ;
2014-10-06 16:05:13 +04:00
hdr = eth_hdr ( skb ) ;
hdr - > h_proto = mpls - > mpls_ethertype ;
2014-12-24 03:20:28 +03:00
if ( ! skb - > inner_protocol )
skb_set_inner_protocol ( skb , skb - > protocol ) ;
2014-10-06 16:05:13 +04:00
skb - > protocol = mpls - > mpls_ethertype ;
2014-11-06 17:55:14 +03:00
invalidate_flow_key ( key ) ;
2014-10-06 16:05:13 +04:00
return 0 ;
}
2014-11-06 17:55:14 +03:00
static int pop_mpls ( struct sk_buff * skb , struct sw_flow_key * key ,
const __be16 ethertype )
2014-10-06 16:05:13 +04:00
{
struct ethhdr * hdr ;
int err ;
2014-11-19 16:05:01 +03:00
err = skb_ensure_writable ( skb , skb - > mac_len + MPLS_HLEN ) ;
2014-10-06 16:05:13 +04:00
if ( unlikely ( err ) )
return err ;
2014-11-19 16:04:55 +03:00
skb_postpull_rcsum ( skb , skb_mpls_header ( skb ) , MPLS_HLEN ) ;
2014-10-06 16:05:13 +04:00
memmove ( skb_mac_header ( skb ) + MPLS_HLEN , skb_mac_header ( skb ) ,
skb - > mac_len ) ;
__skb_pull ( skb , MPLS_HLEN ) ;
skb_reset_mac_header ( skb ) ;
/* skb_mpls_header() is used to locate the ethertype
* field correctly in the presence of VLAN tags .
*/
hdr = ( struct ethhdr * ) ( skb_mpls_header ( skb ) - ETH_HLEN ) ;
hdr - > h_proto = ethertype ;
if ( eth_p_mpls ( skb - > protocol ) )
skb - > protocol = ethertype ;
2014-11-06 17:55:14 +03:00
invalidate_flow_key ( key ) ;
2014-10-06 16:05:13 +04:00
return 0 ;
}
2015-02-06 00:40:49 +03:00
static int set_mpls ( struct sk_buff * skb , struct sw_flow_key * flow_key ,
const __be32 * mpls_lse , const __be32 * mask )
2014-10-06 16:05:13 +04:00
{
__be32 * stack ;
2015-02-06 00:40:49 +03:00
__be32 lse ;
2014-10-06 16:05:13 +04:00
int err ;
2014-11-19 16:05:01 +03:00
err = skb_ensure_writable ( skb , skb - > mac_len + MPLS_HLEN ) ;
2014-10-06 16:05:13 +04:00
if ( unlikely ( err ) )
return err ;
stack = ( __be32 * ) skb_mpls_header ( skb ) ;
2015-08-26 21:31:45 +03:00
lse = OVS_MASKED ( * stack , * mpls_lse , * mask ) ;
2014-10-06 16:05:13 +04:00
if ( skb - > ip_summed = = CHECKSUM_COMPLETE ) {
2015-02-06 00:40:49 +03:00
__be32 diff [ ] = { ~ ( * stack ) , lse } ;
2014-10-06 16:05:13 +04:00
skb - > csum = ~ csum_partial ( ( char * ) diff , sizeof ( diff ) ,
~ skb - > csum ) ;
}
2015-02-06 00:40:49 +03:00
* stack = lse ;
flow_key - > mpls . top_lse = lse ;
2014-10-06 16:05:13 +04:00
return 0 ;
}
2014-11-06 17:55:14 +03:00
static int pop_vlan ( struct sk_buff * skb , struct sw_flow_key * key )
2011-10-26 06:26:31 +04:00
{
int err ;
2014-11-19 16:05:02 +03:00
err = skb_vlan_pop ( skb ) ;
2015-01-13 19:13:44 +03:00
if ( skb_vlan_tag_present ( skb ) )
2014-11-19 16:05:02 +03:00
invalidate_flow_key ( key ) ;
else
2014-11-06 17:55:14 +03:00
key - > eth . tci = 0 ;
2014-11-19 16:05:02 +03:00
return err ;
2011-10-26 06:26:31 +04:00
}
2014-11-06 17:55:14 +03:00
static int push_vlan ( struct sk_buff * skb , struct sw_flow_key * key ,
const struct ovs_action_push_vlan * vlan )
2011-10-26 06:26:31 +04:00
{
2015-01-13 19:13:44 +03:00
if ( skb_vlan_tag_present ( skb ) )
2014-11-06 17:55:14 +03:00
invalidate_flow_key ( key ) ;
2014-11-19 16:05:02 +03:00
else
2014-11-06 17:55:14 +03:00
key - > eth . tci = vlan - > vlan_tci ;
2014-11-19 16:05:02 +03:00
return skb_vlan_push ( skb , vlan - > vlan_tpid ,
ntohs ( vlan - > vlan_tci ) & ~ VLAN_TAG_PRESENT ) ;
2011-10-26 06:26:31 +04:00
}
2015-02-06 00:40:49 +03:00
/* 'src' is already properly masked. */
static void ether_addr_copy_masked ( u8 * dst_ , const u8 * src_ , const u8 * mask_ )
{
u16 * dst = ( u16 * ) dst_ ;
const u16 * src = ( const u16 * ) src_ ;
const u16 * mask = ( const u16 * ) mask_ ;
2015-08-26 21:31:45 +03:00
OVS_SET_MASKED ( dst [ 0 ] , src [ 0 ] , mask [ 0 ] ) ;
OVS_SET_MASKED ( dst [ 1 ] , src [ 1 ] , mask [ 1 ] ) ;
OVS_SET_MASKED ( dst [ 2 ] , src [ 2 ] , mask [ 2 ] ) ;
2015-02-06 00:40:49 +03:00
}
static int set_eth_addr ( struct sk_buff * skb , struct sw_flow_key * flow_key ,
const struct ovs_key_ethernet * key ,
const struct ovs_key_ethernet * mask )
2011-10-26 06:26:31 +04:00
{
int err ;
2015-02-06 00:40:49 +03:00
2014-11-19 16:05:01 +03:00
err = skb_ensure_writable ( skb , ETH_HLEN ) ;
2011-10-26 06:26:31 +04:00
if ( unlikely ( err ) )
return err ;
2013-06-13 22:11:44 +04:00
skb_postpull_rcsum ( skb , eth_hdr ( skb ) , ETH_ALEN * 2 ) ;
2015-02-06 00:40:49 +03:00
ether_addr_copy_masked ( eth_hdr ( skb ) - > h_source , key - > eth_src ,
mask - > eth_src ) ;
ether_addr_copy_masked ( eth_hdr ( skb ) - > h_dest , key - > eth_dst ,
mask - > eth_dst ) ;
2011-10-26 06:26:31 +04:00
2016-02-20 02:29:30 +03:00
skb_postpush_rcsum ( skb , eth_hdr ( skb ) , ETH_ALEN * 2 ) ;
2013-06-13 22:11:44 +04:00
2015-02-06 00:40:49 +03:00
ether_addr_copy ( flow_key - > eth . src , eth_hdr ( skb ) - > h_source ) ;
ether_addr_copy ( flow_key - > eth . dst , eth_hdr ( skb ) - > h_dest ) ;
2011-10-26 06:26:31 +04:00
return 0 ;
}
2015-08-03 19:56:54 +03:00
static void update_ip_l4_checksum ( struct sk_buff * skb , struct iphdr * nh ,
__be32 addr , __be32 new_addr )
2011-10-26 06:26:31 +04:00
{
int transport_len = skb - > len - skb_transport_offset ( skb ) ;
2015-08-03 19:56:54 +03:00
if ( nh - > frag_off & htons ( IP_OFFSET ) )
return ;
2011-10-26 06:26:31 +04:00
if ( nh - > protocol = = IPPROTO_TCP ) {
if ( likely ( transport_len > = sizeof ( struct tcphdr ) ) )
inet_proto_csum_replace4 ( & tcp_hdr ( skb ) - > check , skb ,
2015-08-17 23:42:25 +03:00
addr , new_addr , true ) ;
2011-10-26 06:26:31 +04:00
} else if ( nh - > protocol = = IPPROTO_UDP ) {
2012-03-07 03:05:46 +04:00
if ( likely ( transport_len > = sizeof ( struct udphdr ) ) ) {
struct udphdr * uh = udp_hdr ( skb ) ;
if ( uh - > check | | skb - > ip_summed = = CHECKSUM_PARTIAL ) {
inet_proto_csum_replace4 ( & uh - > check , skb ,
2015-08-17 23:42:25 +03:00
addr , new_addr , true ) ;
2012-03-07 03:05:46 +04:00
if ( ! uh - > check )
uh - > check = CSUM_MANGLED_0 ;
}
}
2011-10-26 06:26:31 +04:00
}
2015-08-03 19:56:54 +03:00
}
2011-10-26 06:26:31 +04:00
2015-08-03 19:56:54 +03:00
static void set_ip_addr ( struct sk_buff * skb , struct iphdr * nh ,
__be32 * addr , __be32 new_addr )
{
update_ip_l4_checksum ( skb , nh , * addr , new_addr ) ;
2011-10-26 06:26:31 +04:00
csum_replace4 ( & nh - > check , * addr , new_addr ) ;
2013-12-16 10:12:18 +04:00
skb_clear_hash ( skb ) ;
2011-10-26 06:26:31 +04:00
* addr = new_addr ;
}
2012-11-14 03:44:14 +04:00
static void update_ipv6_checksum ( struct sk_buff * skb , u8 l4_proto ,
__be32 addr [ 4 ] , const __be32 new_addr [ 4 ] )
{
int transport_len = skb - > len - skb_transport_offset ( skb ) ;
2014-11-12 01:32:20 +03:00
if ( l4_proto = = NEXTHDR_TCP ) {
2012-11-14 03:44:14 +04:00
if ( likely ( transport_len > = sizeof ( struct tcphdr ) ) )
inet_proto_csum_replace16 ( & tcp_hdr ( skb ) - > check , skb ,
2015-08-17 23:42:25 +03:00
addr , new_addr , true ) ;
2014-11-12 01:32:20 +03:00
} else if ( l4_proto = = NEXTHDR_UDP ) {
2012-11-14 03:44:14 +04:00
if ( likely ( transport_len > = sizeof ( struct udphdr ) ) ) {
struct udphdr * uh = udp_hdr ( skb ) ;
if ( uh - > check | | skb - > ip_summed = = CHECKSUM_PARTIAL ) {
inet_proto_csum_replace16 ( & uh - > check , skb ,
2015-08-17 23:42:25 +03:00
addr , new_addr , true ) ;
2012-11-14 03:44:14 +04:00
if ( ! uh - > check )
uh - > check = CSUM_MANGLED_0 ;
}
}
2014-11-12 01:32:20 +03:00
} else if ( l4_proto = = NEXTHDR_ICMP ) {
if ( likely ( transport_len > = sizeof ( struct icmp6hdr ) ) )
inet_proto_csum_replace16 ( & icmp6_hdr ( skb ) - > icmp6_cksum ,
2015-08-17 23:42:25 +03:00
skb , addr , new_addr , true ) ;
2012-11-14 03:44:14 +04:00
}
}
2015-02-06 00:40:49 +03:00
static void mask_ipv6_addr ( const __be32 old [ 4 ] , const __be32 addr [ 4 ] ,
const __be32 mask [ 4 ] , __be32 masked [ 4 ] )
{
2015-08-26 21:31:45 +03:00
masked [ 0 ] = OVS_MASKED ( old [ 0 ] , addr [ 0 ] , mask [ 0 ] ) ;
masked [ 1 ] = OVS_MASKED ( old [ 1 ] , addr [ 1 ] , mask [ 1 ] ) ;
masked [ 2 ] = OVS_MASKED ( old [ 2 ] , addr [ 2 ] , mask [ 2 ] ) ;
masked [ 3 ] = OVS_MASKED ( old [ 3 ] , addr [ 3 ] , mask [ 3 ] ) ;
2015-02-06 00:40:49 +03:00
}
2012-11-14 03:44:14 +04:00
static void set_ipv6_addr ( struct sk_buff * skb , u8 l4_proto ,
__be32 addr [ 4 ] , const __be32 new_addr [ 4 ] ,
bool recalculate_csum )
{
if ( recalculate_csum )
update_ipv6_checksum ( skb , l4_proto , addr , new_addr ) ;
2013-12-16 10:12:18 +04:00
skb_clear_hash ( skb ) ;
2012-11-14 03:44:14 +04:00
memcpy ( addr , new_addr , sizeof ( __be32 [ 4 ] ) ) ;
}
2015-02-06 00:40:49 +03:00
static void set_ipv6_fl ( struct ipv6hdr * nh , u32 fl , u32 mask )
2012-11-14 03:44:14 +04:00
{
2015-02-06 00:40:49 +03:00
/* Bits 21-24 are always unmasked, so this retains their values. */
2015-08-26 21:31:45 +03:00
OVS_SET_MASKED ( nh - > flow_lbl [ 0 ] , ( u8 ) ( fl > > 16 ) , ( u8 ) ( mask > > 16 ) ) ;
OVS_SET_MASKED ( nh - > flow_lbl [ 1 ] , ( u8 ) ( fl > > 8 ) , ( u8 ) ( mask > > 8 ) ) ;
OVS_SET_MASKED ( nh - > flow_lbl [ 2 ] , ( u8 ) fl , ( u8 ) mask ) ;
2012-11-14 03:44:14 +04:00
}
2015-02-06 00:40:49 +03:00
static void set_ip_ttl ( struct sk_buff * skb , struct iphdr * nh , u8 new_ttl ,
u8 mask )
2012-11-14 03:44:14 +04:00
{
2015-08-26 21:31:45 +03:00
new_ttl = OVS_MASKED ( nh - > ttl , new_ttl , mask ) ;
2012-11-14 03:44:14 +04:00
2011-10-26 06:26:31 +04:00
csum_replace2 ( & nh - > check , htons ( nh - > ttl < < 8 ) , htons ( new_ttl < < 8 ) ) ;
nh - > ttl = new_ttl ;
}
2015-02-06 00:40:49 +03:00
static int set_ipv4 ( struct sk_buff * skb , struct sw_flow_key * flow_key ,
const struct ovs_key_ipv4 * key ,
const struct ovs_key_ipv4 * mask )
2011-10-26 06:26:31 +04:00
{
struct iphdr * nh ;
2015-02-06 00:40:49 +03:00
__be32 new_addr ;
2011-10-26 06:26:31 +04:00
int err ;
2014-11-19 16:05:01 +03:00
err = skb_ensure_writable ( skb , skb_network_offset ( skb ) +
sizeof ( struct iphdr ) ) ;
2011-10-26 06:26:31 +04:00
if ( unlikely ( err ) )
return err ;
nh = ip_hdr ( skb ) ;
2015-02-06 00:40:49 +03:00
/* Setting an IP addresses is typically only a side effect of
* matching on them in the current userspace implementation , so it
* makes sense to check if the value actually changed .
*/
if ( mask - > ipv4_src ) {
2015-08-26 21:31:45 +03:00
new_addr = OVS_MASKED ( nh - > saddr , key - > ipv4_src , mask - > ipv4_src ) ;
2011-10-26 06:26:31 +04:00
2015-02-06 00:40:49 +03:00
if ( unlikely ( new_addr ! = nh - > saddr ) ) {
set_ip_addr ( skb , nh , & nh - > saddr , new_addr ) ;
flow_key - > ipv4 . addr . src = new_addr ;
}
2014-11-06 17:55:14 +03:00
}
2015-02-06 00:40:49 +03:00
if ( mask - > ipv4_dst ) {
2015-08-26 21:31:45 +03:00
new_addr = OVS_MASKED ( nh - > daddr , key - > ipv4_dst , mask - > ipv4_dst ) ;
2011-10-26 06:26:31 +04:00
2015-02-06 00:40:49 +03:00
if ( unlikely ( new_addr ! = nh - > daddr ) ) {
set_ip_addr ( skb , nh , & nh - > daddr , new_addr ) ;
flow_key - > ipv4 . addr . dst = new_addr ;
}
2014-11-06 17:55:14 +03:00
}
2015-02-06 00:40:49 +03:00
if ( mask - > ipv4_tos ) {
ipv4_change_dsfield ( nh , ~ mask - > ipv4_tos , key - > ipv4_tos ) ;
flow_key - > ip . tos = nh - > tos ;
}
if ( mask - > ipv4_ttl ) {
set_ip_ttl ( skb , nh , key - > ipv4_ttl , mask - > ipv4_ttl ) ;
flow_key - > ip . ttl = nh - > ttl ;
2014-11-06 17:55:14 +03:00
}
2011-10-26 06:26:31 +04:00
return 0 ;
}
2015-02-06 00:40:49 +03:00
static bool is_ipv6_mask_nonzero ( const __be32 addr [ 4 ] )
{
return ! ! ( addr [ 0 ] | addr [ 1 ] | addr [ 2 ] | addr [ 3 ] ) ;
}
static int set_ipv6 ( struct sk_buff * skb , struct sw_flow_key * flow_key ,
const struct ovs_key_ipv6 * key ,
const struct ovs_key_ipv6 * mask )
2012-11-14 03:44:14 +04:00
{
struct ipv6hdr * nh ;
int err ;
2014-11-19 16:05:01 +03:00
err = skb_ensure_writable ( skb , skb_network_offset ( skb ) +
sizeof ( struct ipv6hdr ) ) ;
2012-11-14 03:44:14 +04:00
if ( unlikely ( err ) )
return err ;
nh = ipv6_hdr ( skb ) ;
2015-02-06 00:40:49 +03:00
/* Setting an IP addresses is typically only a side effect of
* matching on them in the current userspace implementation , so it
* makes sense to check if the value actually changed .
*/
if ( is_ipv6_mask_nonzero ( mask - > ipv6_src ) ) {
__be32 * saddr = ( __be32 * ) & nh - > saddr ;
__be32 masked [ 4 ] ;
mask_ipv6_addr ( saddr , key - > ipv6_src , mask - > ipv6_src , masked ) ;
if ( unlikely ( memcmp ( saddr , masked , sizeof ( masked ) ) ) ) {
set_ipv6_addr ( skb , key - > ipv6_proto , saddr , masked ,
true ) ;
memcpy ( & flow_key - > ipv6 . addr . src , masked ,
sizeof ( flow_key - > ipv6 . addr . src ) ) ;
}
}
if ( is_ipv6_mask_nonzero ( mask - > ipv6_dst ) ) {
2012-11-14 03:44:14 +04:00
unsigned int offset = 0 ;
int flags = IP6_FH_F_SKIP_RH ;
bool recalc_csum = true ;
2015-02-06 00:40:49 +03:00
__be32 * daddr = ( __be32 * ) & nh - > daddr ;
__be32 masked [ 4 ] ;
mask_ipv6_addr ( daddr , key - > ipv6_dst , mask - > ipv6_dst , masked ) ;
if ( unlikely ( memcmp ( daddr , masked , sizeof ( masked ) ) ) ) {
if ( ipv6_ext_hdr ( nh - > nexthdr ) )
recalc_csum = ( ipv6_find_hdr ( skb , & offset ,
NEXTHDR_ROUTING ,
NULL , & flags )
! = NEXTHDR_ROUTING ) ;
set_ipv6_addr ( skb , key - > ipv6_proto , daddr , masked ,
recalc_csum ) ;
memcpy ( & flow_key - > ipv6 . addr . dst , masked ,
sizeof ( flow_key - > ipv6 . addr . dst ) ) ;
}
}
if ( mask - > ipv6_tclass ) {
ipv6_change_dsfield ( nh , ~ mask - > ipv6_tclass , key - > ipv6_tclass ) ;
flow_key - > ip . tos = ipv6_get_dsfield ( nh ) ;
}
if ( mask - > ipv6_label ) {
set_ipv6_fl ( nh , ntohl ( key - > ipv6_label ) ,
ntohl ( mask - > ipv6_label ) ) ;
flow_key - > ipv6 . label =
* ( __be32 * ) nh & htonl ( IPV6_FLOWINFO_FLOWLABEL ) ;
}
if ( mask - > ipv6_hlimit ) {
2015-08-26 21:31:45 +03:00
OVS_SET_MASKED ( nh - > hop_limit , key - > ipv6_hlimit ,
mask - > ipv6_hlimit ) ;
2015-02-06 00:40:49 +03:00
flow_key - > ip . ttl = nh - > hop_limit ;
2012-11-14 03:44:14 +04:00
}
return 0 ;
}
2014-11-19 16:05:01 +03:00
/* Must follow skb_ensure_writable() since that can move the skb data. */
2011-10-26 06:26:31 +04:00
static void set_tp_port ( struct sk_buff * skb , __be16 * port ,
2015-02-06 00:40:49 +03:00
__be16 new_port , __sum16 * check )
2011-10-26 06:26:31 +04:00
{
2015-08-17 23:42:25 +03:00
inet_proto_csum_replace2 ( check , skb , * port , new_port , false ) ;
2011-10-26 06:26:31 +04:00
* port = new_port ;
2012-03-07 03:05:46 +04:00
}
2015-02-06 00:40:49 +03:00
static int set_udp ( struct sk_buff * skb , struct sw_flow_key * flow_key ,
const struct ovs_key_udp * key ,
const struct ovs_key_udp * mask )
2011-10-26 06:26:31 +04:00
{
struct udphdr * uh ;
2015-02-06 00:40:49 +03:00
__be16 src , dst ;
2011-10-26 06:26:31 +04:00
int err ;
2014-11-19 16:05:01 +03:00
err = skb_ensure_writable ( skb , skb_transport_offset ( skb ) +
sizeof ( struct udphdr ) ) ;
2011-10-26 06:26:31 +04:00
if ( unlikely ( err ) )
return err ;
uh = udp_hdr ( skb ) ;
2015-02-06 00:40:49 +03:00
/* Either of the masks is non-zero, so do not bother checking them. */
2015-08-26 21:31:45 +03:00
src = OVS_MASKED ( uh - > source , key - > udp_src , mask - > udp_src ) ;
dst = OVS_MASKED ( uh - > dest , key - > udp_dst , mask - > udp_dst ) ;
2011-10-26 06:26:31 +04:00
2015-02-06 00:40:49 +03:00
if ( uh - > check & & skb - > ip_summed ! = CHECKSUM_PARTIAL ) {
if ( likely ( src ! = uh - > source ) ) {
set_tp_port ( skb , & uh - > source , src , & uh - > check ) ;
flow_key - > tp . src = src ;
}
if ( likely ( dst ! = uh - > dest ) ) {
set_tp_port ( skb , & uh - > dest , dst , & uh - > check ) ;
flow_key - > tp . dst = dst ;
}
if ( unlikely ( ! uh - > check ) )
uh - > check = CSUM_MANGLED_0 ;
} else {
uh - > source = src ;
uh - > dest = dst ;
flow_key - > tp . src = src ;
flow_key - > tp . dst = dst ;
2014-11-06 17:55:14 +03:00
}
2011-10-26 06:26:31 +04:00
2015-02-06 00:40:49 +03:00
skb_clear_hash ( skb ) ;
2011-10-26 06:26:31 +04:00
return 0 ;
}
2015-02-06 00:40:49 +03:00
static int set_tcp ( struct sk_buff * skb , struct sw_flow_key * flow_key ,
const struct ovs_key_tcp * key ,
const struct ovs_key_tcp * mask )
2011-10-26 06:26:31 +04:00
{
struct tcphdr * th ;
2015-02-06 00:40:49 +03:00
__be16 src , dst ;
2011-10-26 06:26:31 +04:00
int err ;
2014-11-19 16:05:01 +03:00
err = skb_ensure_writable ( skb , skb_transport_offset ( skb ) +
sizeof ( struct tcphdr ) ) ;
2011-10-26 06:26:31 +04:00
if ( unlikely ( err ) )
return err ;
th = tcp_hdr ( skb ) ;
2015-08-26 21:31:45 +03:00
src = OVS_MASKED ( th - > source , key - > tcp_src , mask - > tcp_src ) ;
2015-02-06 00:40:49 +03:00
if ( likely ( src ! = th - > source ) ) {
set_tp_port ( skb , & th - > source , src , & th - > check ) ;
flow_key - > tp . src = src ;
2014-11-06 17:55:14 +03:00
}
2015-08-26 21:31:45 +03:00
dst = OVS_MASKED ( th - > dest , key - > tcp_dst , mask - > tcp_dst ) ;
2015-02-06 00:40:49 +03:00
if ( likely ( dst ! = th - > dest ) ) {
set_tp_port ( skb , & th - > dest , dst , & th - > check ) ;
flow_key - > tp . dst = dst ;
2014-11-06 17:55:14 +03:00
}
2015-02-06 00:40:49 +03:00
skb_clear_hash ( skb ) ;
2011-10-26 06:26:31 +04:00
return 0 ;
}
2015-02-06 00:40:49 +03:00
static int set_sctp ( struct sk_buff * skb , struct sw_flow_key * flow_key ,
const struct ovs_key_sctp * key ,
const struct ovs_key_sctp * mask )
2013-08-22 23:30:48 +04:00
{
2015-02-06 00:40:49 +03:00
unsigned int sctphoff = skb_transport_offset ( skb ) ;
2013-08-22 23:30:48 +04:00
struct sctphdr * sh ;
2015-02-06 00:40:49 +03:00
__le32 old_correct_csum , new_csum , old_csum ;
2013-08-22 23:30:48 +04:00
int err ;
2014-11-19 16:05:01 +03:00
err = skb_ensure_writable ( skb , sctphoff + sizeof ( struct sctphdr ) ) ;
2013-08-22 23:30:48 +04:00
if ( unlikely ( err ) )
return err ;
sh = sctp_hdr ( skb ) ;
2015-02-06 00:40:49 +03:00
old_csum = sh - > checksum ;
old_correct_csum = sctp_compute_cksum ( skb , sctphoff ) ;
2013-08-22 23:30:48 +04:00
2015-08-26 21:31:45 +03:00
sh - > source = OVS_MASKED ( sh - > source , key - > sctp_src , mask - > sctp_src ) ;
sh - > dest = OVS_MASKED ( sh - > dest , key - > sctp_dst , mask - > sctp_dst ) ;
2013-08-22 23:30:48 +04:00
2015-02-06 00:40:49 +03:00
new_csum = sctp_compute_cksum ( skb , sctphoff ) ;
2013-08-22 23:30:48 +04:00
2015-02-06 00:40:49 +03:00
/* Carry any checksum errors through. */
sh - > checksum = old_csum ^ old_correct_csum ^ new_csum ;
2013-08-22 23:30:48 +04:00
2015-02-06 00:40:49 +03:00
skb_clear_hash ( skb ) ;
flow_key - > tp . src = sh - > source ;
flow_key - > tp . dst = sh - > dest ;
2013-08-22 23:30:48 +04:00
return 0 ;
}
2015-09-15 04:08:51 +03:00
static int ovs_vport_output ( struct net * net , struct sock * sk , struct sk_buff * skb )
2015-08-26 21:31:48 +03:00
{
struct ovs_frag_data * data = this_cpu_ptr ( & ovs_frag_data_storage ) ;
struct vport * vport = data - > vport ;
if ( skb_cow_head ( skb , data - > l2_len ) < 0 ) {
kfree_skb ( skb ) ;
return - ENOMEM ;
}
__skb_dst_copy ( skb , data - > dst ) ;
* OVS_CB ( skb ) = data - > cb ;
skb - > inner_protocol = data - > inner_protocol ;
skb - > vlan_tci = data - > vlan_tci ;
skb - > vlan_proto = data - > vlan_proto ;
/* Reconstruct the MAC header. */
skb_push ( skb , data - > l2_len ) ;
memcpy ( skb - > data , & data - > l2_data , data - > l2_len ) ;
2016-02-20 02:29:30 +03:00
skb_postpush_rcsum ( skb , skb - > data , data - > l2_len ) ;
2015-08-26 21:31:48 +03:00
skb_reset_mac_header ( skb ) ;
ovs_vport_send ( vport , skb ) ;
return 0 ;
}
static unsigned int
ovs_dst_get_mtu ( const struct dst_entry * dst )
{
return dst - > dev - > mtu ;
}
static struct dst_ops ovs_dst_ops = {
. family = AF_UNSPEC ,
. mtu = ovs_dst_get_mtu ,
} ;
/* prepare_frag() is called once per (larger-than-MTU) frame; its inverse is
* ovs_vport_output ( ) , which is called once per fragmented packet .
*/
static void prepare_frag ( struct vport * vport , struct sk_buff * skb )
{
unsigned int hlen = skb_network_offset ( skb ) ;
struct ovs_frag_data * data ;
data = this_cpu_ptr ( & ovs_frag_data_storage ) ;
data - > dst = skb - > _skb_refdst ;
data - > vport = vport ;
data - > cb = * OVS_CB ( skb ) ;
data - > inner_protocol = skb - > inner_protocol ;
data - > vlan_tci = skb - > vlan_tci ;
data - > vlan_proto = skb - > vlan_proto ;
data - > l2_len = hlen ;
memcpy ( & data - > l2_data , skb - > data , hlen ) ;
memset ( IPCB ( skb ) , 0 , sizeof ( struct inet_skb_parm ) ) ;
skb_pull ( skb , hlen ) ;
}
2015-09-15 04:10:28 +03:00
static void ovs_fragment ( struct net * net , struct vport * vport ,
struct sk_buff * skb , u16 mru , __be16 ethertype )
2015-08-26 21:31:48 +03:00
{
if ( skb_network_offset ( skb ) > MAX_L2_LEN ) {
OVS_NLERR ( 1 , " L2 header too long to fragment " ) ;
2015-10-06 20:59:57 +03:00
goto err ;
2015-08-26 21:31:48 +03:00
}
if ( ethertype = = htons ( ETH_P_IP ) ) {
struct dst_entry ovs_dst ;
unsigned long orig_dst ;
prepare_frag ( vport , skb ) ;
dst_init ( & ovs_dst , & ovs_dst_ops , NULL , 1 ,
DST_OBSOLETE_NONE , DST_NOCOUNT ) ;
ovs_dst . dev = vport - > dev ;
orig_dst = skb - > _skb_refdst ;
skb_dst_set_noref ( skb , & ovs_dst ) ;
IPCB ( skb ) - > frag_max_size = mru ;
2015-06-13 05:55:31 +03:00
ip_do_fragment ( net , skb - > sk , skb , ovs_vport_output ) ;
2015-08-26 21:31:48 +03:00
refdst_drop ( orig_dst ) ;
} else if ( ethertype = = htons ( ETH_P_IPV6 ) ) {
const struct nf_ipv6_ops * v6ops = nf_get_ipv6_ops ( ) ;
unsigned long orig_dst ;
struct rt6_info ovs_rt ;
if ( ! v6ops ) {
2015-10-06 20:59:57 +03:00
goto err ;
2015-08-26 21:31:48 +03:00
}
prepare_frag ( vport , skb ) ;
memset ( & ovs_rt , 0 , sizeof ( ovs_rt ) ) ;
dst_init ( & ovs_rt . dst , & ovs_dst_ops , NULL , 1 ,
DST_OBSOLETE_NONE , DST_NOCOUNT ) ;
ovs_rt . dst . dev = vport - > dev ;
orig_dst = skb - > _skb_refdst ;
skb_dst_set_noref ( skb , & ovs_rt . dst ) ;
IP6CB ( skb ) - > frag_max_size = mru ;
2015-06-13 06:12:04 +03:00
v6ops - > fragment ( net , skb - > sk , skb , ovs_vport_output ) ;
2015-08-26 21:31:48 +03:00
refdst_drop ( orig_dst ) ;
} else {
WARN_ONCE ( 1 , " Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d. " ,
ovs_vport_name ( vport ) , ntohs ( ethertype ) , mru ,
vport - > dev - > mtu ) ;
2015-10-06 20:59:57 +03:00
goto err ;
2015-08-26 21:31:48 +03:00
}
2015-10-06 20:59:57 +03:00
return ;
err :
kfree_skb ( skb ) ;
2015-08-26 21:31:48 +03:00
}
static void do_output ( struct datapath * dp , struct sk_buff * skb , int out_port ,
struct sw_flow_key * key )
2011-10-26 06:26:31 +04:00
{
2014-09-08 11:35:02 +04:00
struct vport * vport = ovs_vport_rcu ( dp , out_port ) ;
2011-10-26 06:26:31 +04:00
2015-08-26 21:31:48 +03:00
if ( likely ( vport ) ) {
u16 mru = OVS_CB ( skb ) - > mru ;
if ( likely ( ! mru | | ( skb - > len < = mru + ETH_HLEN ) ) ) {
ovs_vport_send ( vport , skb ) ;
} else if ( mru < = vport - > dev - > mtu ) {
2015-09-15 04:10:28 +03:00
struct net * net = read_pnet ( & dp - > net ) ;
2015-08-26 21:31:48 +03:00
__be16 ethertype = key - > eth . type ;
if ( ! is_flow_key_valid ( key ) ) {
if ( eth_p_mpls ( skb - > protocol ) )
ethertype = skb - > inner_protocol ;
else
ethertype = vlan_get_protocol ( skb ) ;
}
2015-09-15 04:10:28 +03:00
ovs_fragment ( net , vport , skb , mru , ethertype ) ;
2015-08-26 21:31:48 +03:00
} else {
kfree_skb ( skb ) ;
}
} else {
2011-10-26 06:26:31 +04:00
kfree_skb ( skb ) ;
2015-08-26 21:31:48 +03:00
}
2011-10-26 06:26:31 +04:00
}
static int output_userspace ( struct datapath * dp , struct sk_buff * skb ,
2015-05-27 06:59:43 +03:00
struct sw_flow_key * key , const struct nlattr * attr ,
const struct nlattr * actions , int actions_len )
2011-10-26 06:26:31 +04:00
{
struct dp_upcall_info upcall ;
const struct nlattr * a ;
int rem ;
2015-05-27 06:59:43 +03:00
memset ( & upcall , 0 , sizeof ( upcall ) ) ;
2011-10-26 06:26:31 +04:00
upcall . cmd = OVS_PACKET_CMD_ACTION ;
2015-08-26 21:31:48 +03:00
upcall . mru = OVS_CB ( skb ) - > mru ;
2011-10-26 06:26:31 +04:00
for ( a = nla_data ( attr ) , rem = nla_len ( attr ) ; rem > 0 ;
a = nla_next ( a , & rem ) ) {
switch ( nla_type ( a ) ) {
case OVS_USERSPACE_ATTR_USERDATA :
upcall . userdata = a ;
break ;
case OVS_USERSPACE_ATTR_PID :
2012-09-08 00:12:54 +04:00
upcall . portid = nla_get_u32 ( a ) ;
2011-10-26 06:26:31 +04:00
break ;
2014-11-06 17:51:24 +03:00
case OVS_USERSPACE_ATTR_EGRESS_TUN_PORT : {
/* Get out tunnel info. */
struct vport * vport ;
vport = ovs_vport_rcu ( dp , nla_get_u32 ( a ) ) ;
if ( vport ) {
int err ;
2015-10-23 04:17:16 +03:00
err = dev_fill_metadata_dst ( vport - > dev , skb ) ;
if ( ! err )
upcall . egress_tun_info = skb_tunnel_info ( skb ) ;
2014-11-06 17:51:24 +03:00
}
2015-08-31 04:09:38 +03:00
2014-11-06 17:51:24 +03:00
break ;
2011-10-26 06:26:31 +04:00
}
2014-11-06 17:51:24 +03:00
2015-05-27 06:59:43 +03:00
case OVS_USERSPACE_ATTR_ACTIONS : {
/* Include actions. */
upcall . actions = actions ;
upcall . actions_len = actions_len ;
break ;
}
2014-11-06 17:51:24 +03:00
} /* End of switch. */
2011-10-26 06:26:31 +04:00
}
2014-11-06 17:57:27 +03:00
return ovs_dp_upcall ( dp , skb , key , & upcall ) ;
2011-10-26 06:26:31 +04:00
}
static int sample ( struct datapath * dp , struct sk_buff * skb ,
2015-05-27 06:59:43 +03:00
struct sw_flow_key * key , const struct nlattr * attr ,
const struct nlattr * actions , int actions_len )
2011-10-26 06:26:31 +04:00
{
const struct nlattr * acts_list = NULL ;
const struct nlattr * a ;
int rem ;
for ( a = nla_data ( attr ) , rem = nla_len ( attr ) ; rem > 0 ;
a = nla_next ( a , & rem ) ) {
2015-08-05 10:30:47 +03:00
u32 probability ;
2011-10-26 06:26:31 +04:00
switch ( nla_type ( a ) ) {
case OVS_SAMPLE_ATTR_PROBABILITY :
2015-08-05 10:30:47 +03:00
probability = nla_get_u32 ( a ) ;
if ( ! probability | | prandom_u32 ( ) > probability )
2011-10-26 06:26:31 +04:00
return 0 ;
break ;
case OVS_SAMPLE_ATTR_ACTIONS :
acts_list = a ;
break ;
}
}
2014-07-22 02:12:34 +04:00
rem = nla_len ( acts_list ) ;
a = nla_data ( acts_list ) ;
2014-09-16 06:33:50 +04:00
/* Actions list is empty, do nothing */
if ( unlikely ( ! rem ) )
return 0 ;
2014-07-22 02:12:34 +04:00
2014-09-16 06:33:50 +04:00
/* The only known usage of sample action is having a single user-space
* action . Treat this usage as a special case .
* The output_userspace ( ) should clone the skb to be sent to the
* user space . This skb will be consumed by its caller .
2014-07-22 02:12:34 +04:00
*/
2014-09-16 06:33:50 +04:00
if ( likely ( nla_type ( a ) = = OVS_ACTION_ATTR_USERSPACE & &
2014-10-27 10:12:16 +03:00
nla_is_last ( a , rem ) ) )
2015-05-27 06:59:43 +03:00
return output_userspace ( dp , skb , key , a , actions , actions_len ) ;
2014-09-16 06:33:50 +04:00
skb = skb_clone ( skb , GFP_ATOMIC ) ;
if ( ! skb )
/* Skip the sample action when out of memory. */
return 0 ;
2014-09-16 06:37:25 +04:00
if ( ! add_deferred_actions ( skb , key , a ) ) {
if ( net_ratelimit ( ) )
pr_warn ( " %s: deferred actions limit reached, dropping sample action \n " ,
ovs_dp_name ( dp ) ) ;
kfree_skb ( skb ) ;
}
return 0 ;
}
static void execute_hash ( struct sk_buff * skb , struct sw_flow_key * key ,
const struct nlattr * attr )
{
struct ovs_action_hash * hash_act = nla_data ( attr ) ;
u32 hash = 0 ;
/* OVS_HASH_ALG_L4 is the only possible hash algorithm. */
hash = skb_get_hash ( skb ) ;
hash = jhash_1word ( hash , hash_act - > hash_basis ) ;
if ( ! hash )
hash = 0x1 ;
key - > ovs_flow_hash = hash ;
2011-10-26 06:26:31 +04:00
}
2015-02-06 00:40:49 +03:00
static int execute_set_action ( struct sk_buff * skb ,
struct sw_flow_key * flow_key ,
const struct nlattr * a )
{
/* Only tunnel set execution is supported without a mask. */
if ( nla_type ( a ) = = OVS_KEY_ATTR_TUNNEL_INFO ) {
2015-07-21 11:44:03 +03:00
struct ovs_tunnel_info * tun = nla_data ( a ) ;
skb_dst_drop ( skb ) ;
dst_hold ( ( struct dst_entry * ) tun - > tun_dst ) ;
skb_dst_set ( skb , ( struct dst_entry * ) tun - > tun_dst ) ;
2015-02-06 00:40:49 +03:00
return 0 ;
}
return - EINVAL ;
}
/* Mask is at the midpoint of the data. */
# define get_mask(a, type) ((const type)nla_data(a) + 1)
static int execute_masked_set_action ( struct sk_buff * skb ,
struct sw_flow_key * flow_key ,
const struct nlattr * a )
2011-10-26 06:26:31 +04:00
{
int err = 0 ;
2015-02-06 00:40:49 +03:00
switch ( nla_type ( a ) ) {
2011-10-26 06:26:31 +04:00
case OVS_KEY_ATTR_PRIORITY :
2015-08-26 21:31:45 +03:00
OVS_SET_MASKED ( skb - > priority , nla_get_u32 ( a ) ,
* get_mask ( a , u32 * ) ) ;
2015-02-06 00:40:49 +03:00
flow_key - > phy . priority = skb - > priority ;
2011-10-26 06:26:31 +04:00
break ;
2012-11-26 23:24:11 +04:00
case OVS_KEY_ATTR_SKB_MARK :
2015-08-26 21:31:45 +03:00
OVS_SET_MASKED ( skb - > mark , nla_get_u32 ( a ) , * get_mask ( a , u32 * ) ) ;
2015-02-06 00:40:49 +03:00
flow_key - > phy . skb_mark = skb - > mark ;
2012-11-26 23:24:11 +04:00
break ;
2014-10-04 02:35:31 +04:00
case OVS_KEY_ATTR_TUNNEL_INFO :
2015-02-06 00:40:49 +03:00
/* Masked data not supported for tunnel. */
err = - EINVAL ;
2013-06-18 04:50:18 +04:00
break ;
2011-10-26 06:26:31 +04:00
case OVS_KEY_ATTR_ETHERNET :
2015-02-06 00:40:49 +03:00
err = set_eth_addr ( skb , flow_key , nla_data ( a ) ,
get_mask ( a , struct ovs_key_ethernet * ) ) ;
2011-10-26 06:26:31 +04:00
break ;
case OVS_KEY_ATTR_IPV4 :
2015-02-06 00:40:49 +03:00
err = set_ipv4 ( skb , flow_key , nla_data ( a ) ,
get_mask ( a , struct ovs_key_ipv4 * ) ) ;
2011-10-26 06:26:31 +04:00
break ;
2012-11-14 03:44:14 +04:00
case OVS_KEY_ATTR_IPV6 :
2015-02-06 00:40:49 +03:00
err = set_ipv6 ( skb , flow_key , nla_data ( a ) ,
get_mask ( a , struct ovs_key_ipv6 * ) ) ;
2012-11-14 03:44:14 +04:00
break ;
2011-10-26 06:26:31 +04:00
case OVS_KEY_ATTR_TCP :
2015-02-06 00:40:49 +03:00
err = set_tcp ( skb , flow_key , nla_data ( a ) ,
get_mask ( a , struct ovs_key_tcp * ) ) ;
2011-10-26 06:26:31 +04:00
break ;
case OVS_KEY_ATTR_UDP :
2015-02-06 00:40:49 +03:00
err = set_udp ( skb , flow_key , nla_data ( a ) ,
get_mask ( a , struct ovs_key_udp * ) ) ;
2011-10-26 06:26:31 +04:00
break ;
2013-08-22 23:30:48 +04:00
case OVS_KEY_ATTR_SCTP :
2015-02-06 00:40:49 +03:00
err = set_sctp ( skb , flow_key , nla_data ( a ) ,
get_mask ( a , struct ovs_key_sctp * ) ) ;
2013-08-22 23:30:48 +04:00
break ;
2014-10-06 16:05:13 +04:00
case OVS_KEY_ATTR_MPLS :
2015-02-06 00:40:49 +03:00
err = set_mpls ( skb , flow_key , nla_data ( a ) , get_mask ( a ,
__be32 * ) ) ;
2014-10-06 16:05:13 +04:00
break ;
2015-08-26 21:31:48 +03:00
case OVS_KEY_ATTR_CT_STATE :
case OVS_KEY_ATTR_CT_ZONE :
2015-08-26 21:31:49 +03:00
case OVS_KEY_ATTR_CT_MARK :
2015-10-02 01:00:37 +03:00
case OVS_KEY_ATTR_CT_LABELS :
2015-08-26 21:31:48 +03:00
err = - EINVAL ;
break ;
2011-10-26 06:26:31 +04:00
}
return err ;
}
2014-09-16 06:37:25 +04:00
static int execute_recirc ( struct datapath * dp , struct sk_buff * skb ,
struct sw_flow_key * key ,
const struct nlattr * a , int rem )
{
struct deferred_action * da ;
2014-11-06 17:55:14 +03:00
if ( ! is_flow_key_valid ( key ) ) {
int err ;
err = ovs_flow_key_update ( skb , key ) ;
if ( err )
return err ;
}
BUG_ON ( ! is_flow_key_valid ( key ) ) ;
2014-09-16 06:37:25 +04:00
2014-10-27 10:12:16 +03:00
if ( ! nla_is_last ( a , rem ) ) {
2014-09-16 06:37:25 +04:00
/* Recirc action is the not the last action
* of the action list , need to clone the skb .
*/
skb = skb_clone ( skb , GFP_ATOMIC ) ;
/* Skip the recirc action when out of memory, but
* continue on with the rest of the action list .
*/
if ( ! skb )
return 0 ;
}
da = add_deferred_actions ( skb , key , NULL ) ;
if ( da ) {
da - > pkt_key . recirc_id = nla_get_u32 ( a ) ;
} else {
kfree_skb ( skb ) ;
if ( net_ratelimit ( ) )
pr_warn ( " %s: deferred action limit reached, drop recirc action \n " ,
ovs_dp_name ( dp ) ) ;
}
return 0 ;
}
2011-10-26 06:26:31 +04:00
/* Execute a list of actions against 'skb'. */
static int do_execute_actions ( struct datapath * dp , struct sk_buff * skb ,
2014-09-16 06:15:28 +04:00
struct sw_flow_key * key ,
2014-07-22 02:12:34 +04:00
const struct nlattr * attr , int len )
2011-10-26 06:26:31 +04:00
{
/* 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
* then freeing the original skbuff is wasteful . So the following code
2014-11-06 17:55:14 +03:00
* is slightly obscure just to avoid that .
*/
2011-10-26 06:26:31 +04:00
int prev_port = - 1 ;
const struct nlattr * a ;
int rem ;
for ( a = attr , rem = len ; rem > 0 ;
a = nla_next ( a , & rem ) ) {
int err = 0 ;
2014-09-08 11:35:02 +04:00
if ( unlikely ( prev_port ! = - 1 ) ) {
struct sk_buff * out_skb = skb_clone ( skb , GFP_ATOMIC ) ;
if ( out_skb )
2015-08-26 21:31:48 +03:00
do_output ( dp , out_skb , prev_port , key ) ;
2014-09-08 11:35:02 +04:00
2011-10-26 06:26:31 +04:00
prev_port = - 1 ;
}
switch ( nla_type ( a ) ) {
case OVS_ACTION_ATTR_OUTPUT :
prev_port = nla_get_u32 ( a ) ;
break ;
case OVS_ACTION_ATTR_USERSPACE :
2015-05-27 06:59:43 +03:00
output_userspace ( dp , skb , key , a , attr , len ) ;
2011-10-26 06:26:31 +04:00
break ;
2014-09-16 06:37:25 +04:00
case OVS_ACTION_ATTR_HASH :
execute_hash ( skb , key , a ) ;
break ;
2014-10-06 16:05:13 +04:00
case OVS_ACTION_ATTR_PUSH_MPLS :
2014-11-06 17:55:14 +03:00
err = push_mpls ( skb , key , nla_data ( a ) ) ;
2014-10-06 16:05:13 +04:00
break ;
case OVS_ACTION_ATTR_POP_MPLS :
2014-11-06 17:55:14 +03:00
err = pop_mpls ( skb , key , nla_get_be16 ( a ) ) ;
2014-10-06 16:05:13 +04:00
break ;
2011-10-26 06:26:31 +04:00
case OVS_ACTION_ATTR_PUSH_VLAN :
2014-11-06 17:55:14 +03:00
err = push_vlan ( skb , key , nla_data ( a ) ) ;
2011-10-26 06:26:31 +04:00
break ;
case OVS_ACTION_ATTR_POP_VLAN :
2014-11-06 17:55:14 +03:00
err = pop_vlan ( skb , key ) ;
2011-10-26 06:26:31 +04:00
break ;
2014-09-16 06:37:25 +04:00
case OVS_ACTION_ATTR_RECIRC :
err = execute_recirc ( dp , skb , key , a , rem ) ;
2014-10-27 10:12:16 +03:00
if ( nla_is_last ( a , rem ) ) {
2014-09-16 06:37:25 +04:00
/* If this is the last action, the skb has
* been consumed or freed .
* Return immediately .
*/
return err ;
}
break ;
2011-10-26 06:26:31 +04:00
case OVS_ACTION_ATTR_SET :
2014-11-06 17:55:14 +03:00
err = execute_set_action ( skb , key , nla_data ( a ) ) ;
2011-10-26 06:26:31 +04:00
break ;
2015-02-06 00:40:49 +03:00
case OVS_ACTION_ATTR_SET_MASKED :
case OVS_ACTION_ATTR_SET_TO_MASKED :
err = execute_masked_set_action ( skb , key , nla_data ( a ) ) ;
break ;
2011-10-26 06:26:31 +04:00
case OVS_ACTION_ATTR_SAMPLE :
2015-05-27 06:59:43 +03:00
err = sample ( dp , skb , key , a , attr , len ) ;
2011-10-26 06:26:31 +04:00
break ;
2015-08-26 21:31:48 +03:00
case OVS_ACTION_ATTR_CT :
2015-10-06 20:59:58 +03:00
if ( ! is_flow_key_valid ( key ) ) {
err = ovs_flow_key_update ( skb , key ) ;
if ( err )
return err ;
}
2015-08-26 21:31:48 +03:00
err = ovs_ct_execute ( ovs_dp_get_net ( dp ) , skb , key ,
nla_data ( a ) ) ;
/* Hide stolen IP fragments from user space. */
2015-10-26 06:21:48 +03:00
if ( err )
return err = = - EINPROGRESS ? 0 : err ;
2015-08-26 21:31:48 +03:00
break ;
2011-10-26 06:26:31 +04:00
}
if ( unlikely ( err ) ) {
kfree_skb ( skb ) ;
return err ;
}
}
2014-07-22 02:12:34 +04:00
if ( prev_port ! = - 1 )
2015-08-26 21:31:48 +03:00
do_output ( dp , skb , prev_port , key ) ;
2014-07-22 02:12:34 +04:00
else
2011-10-26 06:26:31 +04:00
consume_skb ( skb ) ;
return 0 ;
}
2014-09-16 06:37:25 +04:00
static void process_deferred_actions ( struct datapath * dp )
{
struct action_fifo * fifo = this_cpu_ptr ( action_fifos ) ;
/* Do not touch the FIFO in case there is no deferred actions. */
if ( action_fifo_is_empty ( fifo ) )
return ;
/* Finishing executing all deferred actions. */
do {
struct deferred_action * da = action_fifo_get ( fifo ) ;
struct sk_buff * skb = da - > skb ;
struct sw_flow_key * key = & da - > pkt_key ;
const struct nlattr * actions = da - > actions ;
if ( actions )
do_execute_actions ( dp , skb , key , actions ,
nla_len ( actions ) ) ;
else
ovs_dp_process_packet ( skb , key ) ;
} while ( ! action_fifo_is_empty ( fifo ) ) ;
/* Reset FIFO for the next packet. */
action_fifo_init ( fifo ) ;
}
2011-10-26 06:26:31 +04:00
/* Execute a list of actions against 'skb'. */
2014-09-16 06:15:28 +04:00
int ovs_execute_actions ( struct datapath * dp , struct sk_buff * skb ,
2014-11-06 17:58:52 +03:00
const struct sw_flow_actions * acts ,
struct sw_flow_key * key )
2011-10-26 06:26:31 +04:00
{
2016-01-18 20:03:48 +03:00
static const int ovs_recursion_limit = 5 ;
int err , level ;
level = __this_cpu_inc_return ( exec_actions_level ) ;
if ( unlikely ( level > ovs_recursion_limit ) ) {
net_crit_ratelimited ( " ovs: recursion limit reached on datapath %s, probable configuration error \n " ,
ovs_dp_name ( dp ) ) ;
kfree_skb ( skb ) ;
err = - ENETDOWN ;
goto out ;
}
2014-09-16 06:37:25 +04:00
err = do_execute_actions ( dp , skb , key ,
acts - > actions , acts - > actions_len ) ;
2016-01-18 20:03:48 +03:00
if ( level = = 1 )
2014-09-16 06:37:25 +04:00
process_deferred_actions ( dp ) ;
2016-01-18 20:03:48 +03:00
out :
__this_cpu_dec ( exec_actions_level ) ;
2014-09-16 06:37:25 +04:00
return err ;
}
int action_fifos_init ( void )
{
action_fifos = alloc_percpu ( struct action_fifo ) ;
if ( ! action_fifos )
return - ENOMEM ;
2011-10-26 06:26:31 +04:00
2014-09-16 06:37:25 +04:00
return 0 ;
}
void action_fifos_exit ( void )
{
free_percpu ( action_fifos ) ;
2011-10-26 06:26:31 +04:00
}