aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/bareudp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bareudp.c')
-rw-r--r--drivers/net/bareudp.c52
1 files changed, 34 insertions, 18 deletions
diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
index efd1a1d1f35e..ff0bea1554f9 100644
--- a/drivers/net/bareudp.c
+++ b/drivers/net/bareudp.c
@@ -54,7 +54,6 @@ struct bareudp_dev {
static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
{
struct metadata_dst *tun_dst = NULL;
- struct pcpu_sw_netstats *stats;
struct bareudp_dev *bareudp;
unsigned short family;
unsigned int len;
@@ -125,7 +124,6 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
bareudp->dev->stats.rx_dropped++;
goto drop;
}
-
tun_dst = udp_tun_rx_dst(skb, family, TUNNEL_KEY, 0, 0);
if (!tun_dst) {
bareudp->dev->stats.rx_dropped++;
@@ -161,13 +159,9 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
len = skb->len;
err = gro_cells_receive(&bareudp->gro_cells, skb);
- if (likely(err == NET_RX_SUCCESS)) {
- stats = this_cpu_ptr(bareudp->dev->tstats);
- u64_stats_update_begin(&stats->syncp);
- stats->rx_packets++;
- stats->rx_bytes += len;
- u64_stats_update_end(&stats->syncp);
- }
+ if (likely(err == NET_RX_SUCCESS))
+ dev_sw_netstats_rx_add(bareudp->dev, len);
+
return 0;
drop:
/* Consume bad packet */
@@ -309,7 +303,7 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev,
return PTR_ERR(rt);
skb_tunnel_check_pmtu(skb, &rt->dst,
- BAREUDP_IPV4_HLEN + info->options_len);
+ BAREUDP_IPV4_HLEN + info->options_len, false);
sport = udp_flow_src_port(bareudp->net, skb,
bareudp->sport_min, USHRT_MAX,
@@ -370,7 +364,8 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
if (IS_ERR(dst))
return PTR_ERR(dst);
- skb_tunnel_check_pmtu(skb, dst, BAREUDP_IPV6_HLEN + info->options_len);
+ skb_tunnel_check_pmtu(skb, dst, BAREUDP_IPV6_HLEN + info->options_len,
+ false);
sport = udp_flow_src_port(bareudp->net, skb,
bareudp->sport_min, USHRT_MAX,
@@ -407,19 +402,34 @@ free_dst:
return err;
}
+static bool bareudp_proto_valid(struct bareudp_dev *bareudp, __be16 proto)
+{
+ if (bareudp->ethertype == proto)
+ return true;
+
+ if (!bareudp->multi_proto_mode)
+ return false;
+
+ if (bareudp->ethertype == htons(ETH_P_MPLS_UC) &&
+ proto == htons(ETH_P_MPLS_MC))
+ return true;
+
+ if (bareudp->ethertype == htons(ETH_P_IP) &&
+ proto == htons(ETH_P_IPV6))
+ return true;
+
+ return false;
+}
+
static netdev_tx_t bareudp_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bareudp_dev *bareudp = netdev_priv(dev);
struct ip_tunnel_info *info = NULL;
int err;
- if (skb->protocol != bareudp->ethertype) {
- if (!bareudp->multi_proto_mode ||
- (skb->protocol != htons(ETH_P_MPLS_MC) &&
- skb->protocol != htons(ETH_P_IPV6))) {
- err = -EINVAL;
- goto tx_error;
- }
+ if (!bareudp_proto_valid(bareudp, skb->protocol)) {
+ err = -EINVAL;
+ goto tx_error;
}
info = skb_tunnel_info(skb);
@@ -552,6 +562,8 @@ static int bareudp_validate(struct nlattr *tb[], struct nlattr *data[],
static int bareudp2info(struct nlattr *data[], struct bareudp_conf *conf,
struct netlink_ext_ack *extack)
{
+ memset(conf, 0, sizeof(*conf));
+
if (!data[IFLA_BAREUDP_PORT]) {
NL_SET_ERR_MSG(extack, "port not specified");
return -EINVAL;
@@ -570,6 +582,9 @@ static int bareudp2info(struct nlattr *data[], struct bareudp_conf *conf,
if (data[IFLA_BAREUDP_SRCPORT_MIN])
conf->sport_min = nla_get_u16(data[IFLA_BAREUDP_SRCPORT_MIN]);
+ if (data[IFLA_BAREUDP_MULTIPROTO_MODE])
+ conf->multi_proto_mode = true;
+
return 0;
}
@@ -607,6 +622,7 @@ static int bareudp_configure(struct net *net, struct net_device *dev,
bareudp->ethertype = conf->ethertype;
bareudp->sport_min = conf->sport_min;
bareudp->multi_proto_mode = conf->multi_proto_mode;
+
err = register_netdevice(dev);
if (err)
return err;