Merge branch 'ipvlan-misc'
Mahesh Bandewar says: ==================== IPvlan misc patches This is a collection of unrelated patches for IPvlan driver. a. crub_skb() changes are added to ensure that the packets hit the NF_HOOKS in masters' ns in L3 mode. b. u16 change is bug fix while c. the third patch is to group tx/rx variables in single cacheline ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ea5b2f4406
|
@ -84,19 +84,19 @@ struct ipvl_addr {
|
|||
#define ip4addr ipu.ip4
|
||||
struct hlist_node hlnode; /* Hash-table linkage */
|
||||
struct list_head anode; /* logical-interface linkage */
|
||||
struct rcu_head rcu;
|
||||
ipvl_hdr_type atype;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
struct ipvl_port {
|
||||
struct net_device *dev;
|
||||
struct hlist_head hlhead[IPVLAN_HASH_SIZE];
|
||||
struct list_head ipvlans;
|
||||
struct rcu_head rcu;
|
||||
u16 mode;
|
||||
struct work_struct wq;
|
||||
struct sk_buff_head backlog;
|
||||
int count;
|
||||
u16 mode;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
static inline struct ipvl_port *ipvlan_port_get_rcu(const struct net_device *d)
|
||||
|
@ -114,8 +114,6 @@ static inline struct ipvl_port *ipvlan_port_get_rtnl(const struct net_device *d)
|
|||
return rtnl_dereference(d->rx_handler_data);
|
||||
}
|
||||
|
||||
void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev);
|
||||
void ipvlan_set_port_mode(struct ipvl_port *port, u32 nval);
|
||||
void ipvlan_init_secret(void);
|
||||
unsigned int ipvlan_mac_hash(const unsigned char *addr);
|
||||
rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb);
|
||||
|
@ -125,7 +123,5 @@ void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr);
|
|||
struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
|
||||
const void *iaddr, bool is_v6);
|
||||
bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6);
|
||||
struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
|
||||
const void *iaddr, bool is_v6);
|
||||
void ipvlan_ht_addr_del(struct ipvl_addr *addr);
|
||||
#endif /* __IPVLAN_H */
|
||||
|
|
|
@ -53,8 +53,8 @@ static u8 ipvlan_get_v4_hash(const void *iaddr)
|
|||
IPVLAN_HASH_MASK;
|
||||
}
|
||||
|
||||
struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
|
||||
const void *iaddr, bool is_v6)
|
||||
static struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
|
||||
const void *iaddr, bool is_v6)
|
||||
{
|
||||
struct ipvl_addr *addr;
|
||||
u8 hash;
|
||||
|
@ -265,20 +265,25 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb,
|
|||
struct sk_buff *skb = *pskb;
|
||||
|
||||
len = skb->len + ETH_HLEN;
|
||||
if (unlikely(!(dev->flags & IFF_UP))) {
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
/* Only packets exchanged between two local slaves need to have
|
||||
* device-up check as well as skb-share check.
|
||||
*/
|
||||
if (local) {
|
||||
if (unlikely(!(dev->flags & IFF_UP))) {
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
goto out;
|
||||
|
||||
*pskb = skb;
|
||||
}
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
goto out;
|
||||
|
||||
*pskb = skb;
|
||||
skb->dev = dev;
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
|
||||
if (local) {
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
if (dev_forward_skb(ipvlan->dev, skb) == NET_RX_SUCCESS)
|
||||
success = true;
|
||||
} else {
|
||||
|
@ -342,7 +347,7 @@ static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
|
|||
return addr;
|
||||
}
|
||||
|
||||
static int ipvlan_process_v4_outbound(struct sk_buff *skb)
|
||||
static int ipvlan_process_v4_outbound(struct sk_buff *skb, bool xnet)
|
||||
{
|
||||
const struct iphdr *ip4h = ip_hdr(skb);
|
||||
struct net_device *dev = skb->dev;
|
||||
|
@ -365,7 +370,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
|
|||
ip_rt_put(rt);
|
||||
goto err;
|
||||
}
|
||||
skb_dst_drop(skb);
|
||||
skb_scrub_packet(skb, xnet);
|
||||
skb_dst_set(skb, &rt->dst);
|
||||
err = ip_local_out(net, skb->sk, skb);
|
||||
if (unlikely(net_xmit_eval(err)))
|
||||
|
@ -380,7 +385,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ipvlan_process_v6_outbound(struct sk_buff *skb)
|
||||
static int ipvlan_process_v6_outbound(struct sk_buff *skb, bool xnet)
|
||||
{
|
||||
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||
struct net_device *dev = skb->dev;
|
||||
|
@ -403,7 +408,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
|
|||
dst_release(dst);
|
||||
goto err;
|
||||
}
|
||||
skb_dst_drop(skb);
|
||||
skb_scrub_packet(skb, xnet);
|
||||
skb_dst_set(skb, dst);
|
||||
err = ip6_local_out(net, skb->sk, skb);
|
||||
if (unlikely(net_xmit_eval(err)))
|
||||
|
@ -418,8 +423,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ipvlan_process_outbound(struct sk_buff *skb,
|
||||
const struct ipvl_dev *ipvlan)
|
||||
static int ipvlan_process_outbound(struct sk_buff *skb, bool xnet)
|
||||
{
|
||||
struct ethhdr *ethh = eth_hdr(skb);
|
||||
int ret = NET_XMIT_DROP;
|
||||
|
@ -443,9 +447,9 @@ static int ipvlan_process_outbound(struct sk_buff *skb,
|
|||
}
|
||||
|
||||
if (skb->protocol == htons(ETH_P_IPV6))
|
||||
ret = ipvlan_process_v6_outbound(skb);
|
||||
ret = ipvlan_process_v6_outbound(skb, xnet);
|
||||
else if (skb->protocol == htons(ETH_P_IP))
|
||||
ret = ipvlan_process_v4_outbound(skb);
|
||||
ret = ipvlan_process_v4_outbound(skb, xnet);
|
||||
else {
|
||||
pr_warn_ratelimited("Dropped outbound packet type=%x\n",
|
||||
ntohs(skb->protocol));
|
||||
|
@ -481,6 +485,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
|
|||
void *lyr3h;
|
||||
struct ipvl_addr *addr;
|
||||
int addr_type;
|
||||
bool xnet;
|
||||
|
||||
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
|
||||
if (!lyr3h)
|
||||
|
@ -491,8 +496,9 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
|
|||
return ipvlan_rcv_frame(addr, &skb, true);
|
||||
|
||||
out:
|
||||
xnet = !net_eq(dev_net(skb->dev), dev_net(ipvlan->phy_dev));
|
||||
skb->dev = ipvlan->phy_dev;
|
||||
return ipvlan_process_outbound(skb, ipvlan);
|
||||
return ipvlan_process_outbound(skb, xnet);
|
||||
}
|
||||
|
||||
static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
|
||||
#include "ipvlan.h"
|
||||
|
||||
void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev)
|
||||
static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev)
|
||||
{
|
||||
ipvlan->dev->mtu = dev->mtu - ipvlan->mtu_adj;
|
||||
}
|
||||
|
||||
void ipvlan_set_port_mode(struct ipvl_port *port, u32 nval)
|
||||
static void ipvlan_set_port_mode(struct ipvl_port *port, u16 nval)
|
||||
{
|
||||
struct ipvl_dev *ipvlan;
|
||||
|
||||
|
@ -442,6 +442,7 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
|
|||
struct ipvl_port *port;
|
||||
struct net_device *phy_dev;
|
||||
int err;
|
||||
u16 mode = IPVLAN_MODE_L3;
|
||||
|
||||
if (!tb[IFLA_LINK])
|
||||
return -EINVAL;
|
||||
|
@ -460,10 +461,10 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
|
|||
return err;
|
||||
}
|
||||
|
||||
port = ipvlan_port_get_rtnl(phy_dev);
|
||||
if (data && data[IFLA_IPVLAN_MODE])
|
||||
port->mode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
|
||||
mode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
|
||||
|
||||
port = ipvlan_port_get_rtnl(phy_dev);
|
||||
ipvlan->phy_dev = phy_dev;
|
||||
ipvlan->dev = dev;
|
||||
ipvlan->port = port;
|
||||
|
@ -489,6 +490,8 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
|
|||
goto ipvlan_destroy_port;
|
||||
|
||||
list_add_tail_rcu(&ipvlan->pnode, &port->ipvlans);
|
||||
ipvlan_set_port_mode(port, mode);
|
||||
|
||||
netif_stacked_transfer_operstate(phy_dev, dev);
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Reference in a new issue