aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_forward.c3
-rw-r--r--net/bridge/br_if.c1
-rw-r--r--net/bridge/br_private.h3
-rw-r--r--net/bridge/br_sysfs_if.c17
-rw-r--r--net/core/datagram.c3
-rw-r--r--net/ipv6/icmp.c17
-rw-r--r--net/ipv6/ip6_output.c15
-rw-r--r--net/ipv6/ipv6_sockglue.c5
-rw-r--r--net/ipv6/ndisc.c4
-rw-r--r--net/ipv6/raw.c5
-rw-r--r--net/ipv6/udp.c5
11 files changed, 42 insertions, 36 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index d2c27c808d3b..bc1704ac6cd9 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -22,7 +22,8 @@
22static inline int should_deliver(const struct net_bridge_port *p, 22static inline int should_deliver(const struct net_bridge_port *p,
23 const struct sk_buff *skb) 23 const struct sk_buff *skb)
24{ 24{
25 return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING); 25 return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
26 p->state == BR_STATE_FORWARDING);
26} 27}
27 28
28static inline unsigned packet_length(const struct sk_buff *skb) 29static inline unsigned packet_length(const struct sk_buff *skb)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index eb404dc3ed6e..e486f1fc3632 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -256,6 +256,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
256 p->path_cost = port_cost(dev); 256 p->path_cost = port_cost(dev);
257 p->priority = 0x8000 >> BR_PORT_BITS; 257 p->priority = 0x8000 >> BR_PORT_BITS;
258 p->port_no = index; 258 p->port_no = index;
259 p->flags = 0;
259 br_init_port(p); 260 br_init_port(p);
260 p->state = BR_STATE_DISABLED; 261 p->state = BR_STATE_DISABLED;
261 br_stp_port_timer_init(p); 262 br_stp_port_timer_init(p);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d5b5537272b4..8319247dad5d 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -81,6 +81,9 @@ struct net_bridge_port
81 struct timer_list message_age_timer; 81 struct timer_list message_age_timer;
82 struct kobject kobj; 82 struct kobject kobj;
83 struct rcu_head rcu; 83 struct rcu_head rcu;
84
85 unsigned long flags;
86#define BR_HAIRPIN_MODE 0x00000001
84}; 87};
85 88
86struct net_bridge 89struct net_bridge
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 4a3cdf8f3813..820643a3ba9c 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -143,6 +143,22 @@ static ssize_t store_flush(struct net_bridge_port *p, unsigned long v)
143} 143}
144static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); 144static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);
145 145
146static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf)
147{
148 int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0;
149 return sprintf(buf, "%d\n", hairpin_mode);
150}
151static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v)
152{
153 if (v)
154 p->flags |= BR_HAIRPIN_MODE;
155 else
156 p->flags &= ~BR_HAIRPIN_MODE;
157 return 0;
158}
159static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
160 show_hairpin_mode, store_hairpin_mode);
161
146static struct brport_attribute *brport_attrs[] = { 162static struct brport_attribute *brport_attrs[] = {
147 &brport_attr_path_cost, 163 &brport_attr_path_cost,
148 &brport_attr_priority, 164 &brport_attr_priority,
@@ -159,6 +175,7 @@ static struct brport_attribute *brport_attrs[] = {
159 &brport_attr_forward_delay_timer, 175 &brport_attr_forward_delay_timer,
160 &brport_attr_hold_timer, 176 &brport_attr_hold_timer,
161 &brport_attr_flush, 177 &brport_attr_flush,
178 &brport_attr_hairpin_mode,
162 NULL 179 NULL
163}; 180};
164 181
diff --git a/net/core/datagram.c b/net/core/datagram.c
index b0fe69211eef..1c6cf3a1a4f6 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -55,6 +55,7 @@
55#include <net/checksum.h> 55#include <net/checksum.h>
56#include <net/sock.h> 56#include <net/sock.h>
57#include <net/tcp_states.h> 57#include <net/tcp_states.h>
58#include <trace/events/skb.h>
58 59
59/* 60/*
60 * Is a socket 'connection oriented' ? 61 * Is a socket 'connection oriented' ?
@@ -284,6 +285,8 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
284 int i, copy = start - offset; 285 int i, copy = start - offset;
285 struct sk_buff *frag_iter; 286 struct sk_buff *frag_iter;
286 287
288 trace_skb_copy_datagram_iovec(skb, len);
289
287 /* Copy header. */ 290 /* Copy header. */
288 if (copy > 0) { 291 if (copy > 0) {
289 if (copy > len) 292 if (copy > len)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index eab62a7a8f06..e2325f6a05fb 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -323,7 +323,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
323 int iif = 0; 323 int iif = 0;
324 int addr_type = 0; 324 int addr_type = 0;
325 int len; 325 int len;
326 int hlimit, tclass; 326 int hlimit;
327 int err = 0; 327 int err = 0;
328 328
329 if ((u8 *)hdr < skb->head || 329 if ((u8 *)hdr < skb->head ||
@@ -469,10 +469,6 @@ route_done:
469 if (hlimit < 0) 469 if (hlimit < 0)
470 hlimit = ip6_dst_hoplimit(dst); 470 hlimit = ip6_dst_hoplimit(dst);
471 471
472 tclass = np->tclass;
473 if (tclass < 0)
474 tclass = 0;
475
476 msg.skb = skb; 472 msg.skb = skb;
477 msg.offset = skb_network_offset(skb); 473 msg.offset = skb_network_offset(skb);
478 msg.type = type; 474 msg.type = type;
@@ -488,8 +484,8 @@ route_done:
488 484
489 err = ip6_append_data(sk, icmpv6_getfrag, &msg, 485 err = ip6_append_data(sk, icmpv6_getfrag, &msg,
490 len + sizeof(struct icmp6hdr), 486 len + sizeof(struct icmp6hdr),
491 sizeof(struct icmp6hdr), 487 sizeof(struct icmp6hdr), hlimit,
492 hlimit, tclass, NULL, &fl, (struct rt6_info*)dst, 488 np->tclass, NULL, &fl, (struct rt6_info*)dst,
493 MSG_DONTWAIT); 489 MSG_DONTWAIT);
494 if (err) { 490 if (err) {
495 ip6_flush_pending_frames(sk); 491 ip6_flush_pending_frames(sk);
@@ -522,7 +518,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
522 struct dst_entry *dst; 518 struct dst_entry *dst;
523 int err = 0; 519 int err = 0;
524 int hlimit; 520 int hlimit;
525 int tclass;
526 521
527 saddr = &ipv6_hdr(skb)->daddr; 522 saddr = &ipv6_hdr(skb)->daddr;
528 523
@@ -562,10 +557,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
562 if (hlimit < 0) 557 if (hlimit < 0)
563 hlimit = ip6_dst_hoplimit(dst); 558 hlimit = ip6_dst_hoplimit(dst);
564 559
565 tclass = np->tclass;
566 if (tclass < 0)
567 tclass = 0;
568
569 idev = in6_dev_get(skb->dev); 560 idev = in6_dev_get(skb->dev);
570 561
571 msg.skb = skb; 562 msg.skb = skb;
@@ -573,7 +564,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
573 msg.type = ICMPV6_ECHO_REPLY; 564 msg.type = ICMPV6_ECHO_REPLY;
574 565
575 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), 566 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
576 sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl, 567 sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl,
577 (struct rt6_info*)dst, MSG_DONTWAIT); 568 (struct rt6_info*)dst, MSG_DONTWAIT);
578 569
579 if (err) { 570 if (err) {
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 93beee944657..6ad5aadf81ad 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -194,7 +194,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
194 struct ipv6hdr *hdr; 194 struct ipv6hdr *hdr;
195 u8 proto = fl->proto; 195 u8 proto = fl->proto;
196 int seg_len = skb->len; 196 int seg_len = skb->len;
197 int hlimit, tclass; 197 int hlimit = -1;
198 int tclass = 0;
198 u32 mtu; 199 u32 mtu;
199 200
200 if (opt) { 201 if (opt) {
@@ -237,19 +238,13 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
237 /* 238 /*
238 * Fill in the IPv6 header 239 * Fill in the IPv6 header
239 */ 240 */
240 241 if (np) {
241 hlimit = -1; 242 tclass = np->tclass;
242 if (np)
243 hlimit = np->hop_limit; 243 hlimit = np->hop_limit;
244 }
244 if (hlimit < 0) 245 if (hlimit < 0)
245 hlimit = ip6_dst_hoplimit(dst); 246 hlimit = ip6_dst_hoplimit(dst);
246 247
247 tclass = -1;
248 if (np)
249 tclass = np->tclass;
250 if (tclass < 0)
251 tclass = 0;
252
253 *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; 248 *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel;
254 249
255 hdr->payload_len = htons(seg_len); 250 hdr->payload_len = htons(seg_len);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index a7fdf9a27f15..f5e0682b402d 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -315,6 +315,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
315 goto e_inval; 315 goto e_inval;
316 if (val < -1 || val > 0xff) 316 if (val < -1 || val > 0xff)
317 goto e_inval; 317 goto e_inval;
318 /* RFC 3542, 6.5: default traffic class of 0x0 */
319 if (val == -1)
320 val = 0;
318 np->tclass = val; 321 np->tclass = val;
319 retv = 0; 322 retv = 0;
320 break; 323 break;
@@ -1037,8 +1040,6 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
1037 1040
1038 case IPV6_TCLASS: 1041 case IPV6_TCLASS:
1039 val = np->tclass; 1042 val = np->tclass;
1040 if (val < 0)
1041 val = 0;
1042 break; 1043 break;
1043 1044
1044 case IPV6_RECVTCLASS: 1045 case IPV6_RECVTCLASS:
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 9eb68e92cc18..1ba42bd65577 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -955,8 +955,8 @@ static void ndisc_recv_na(struct sk_buff *skb)
955 */ 955 */
956 if (skb->pkt_type != PACKET_LOOPBACK) 956 if (skb->pkt_type != PACKET_LOOPBACK)
957 ND_PRINTK1(KERN_WARNING 957 ND_PRINTK1(KERN_WARNING
958 "ICMPv6 NA: someone advertises our address on %s!\n", 958 "ICMPv6 NA: someone advertises our address %pI6 on %s!\n",
959 ifp->idev->dev->name); 959 &ifp->addr, ifp->idev->dev->name);
960 in6_ifa_put(ifp); 960 in6_ifa_put(ifp);
961 return; 961 return;
962 } 962 }
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d6c3c1c34b2d..506841030fbe 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -877,11 +877,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
877 hlimit = ip6_dst_hoplimit(dst); 877 hlimit = ip6_dst_hoplimit(dst);
878 } 878 }
879 879
880 if (tclass < 0) { 880 if (tclass < 0)
881 tclass = np->tclass; 881 tclass = np->tclass;
882 if (tclass < 0)
883 tclass = 0;
884 }
885 882
886 if (msg->msg_flags&MSG_CONFIRM) 883 if (msg->msg_flags&MSG_CONFIRM)
887 goto do_confirm; 884 goto do_confirm;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index d79fa6724451..20d2ffc15f0d 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -946,11 +946,8 @@ do_udp_sendmsg:
946 hlimit = ip6_dst_hoplimit(dst); 946 hlimit = ip6_dst_hoplimit(dst);
947 } 947 }
948 948
949 if (tclass < 0) { 949 if (tclass < 0)
950 tclass = np->tclass; 950 tclass = np->tclass;
951 if (tclass < 0)
952 tclass = 0;
953 }
954 951
955 if (msg->msg_flags&MSG_CONFIRM) 952 if (msg->msg_flags&MSG_CONFIRM)
956 goto do_confirm; 953 goto do_confirm;