diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_forward.c | 3 | ||||
-rw-r--r-- | net/bridge/br_if.c | 1 | ||||
-rw-r--r-- | net/bridge/br_private.h | 3 | ||||
-rw-r--r-- | net/bridge/br_sysfs_if.c | 17 | ||||
-rw-r--r-- | net/core/datagram.c | 3 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 17 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 15 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 5 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 4 | ||||
-rw-r--r-- | net/ipv6/raw.c | 5 | ||||
-rw-r--r-- | net/ipv6/udp.c | 5 |
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 @@ | |||
22 | static inline int should_deliver(const struct net_bridge_port *p, | 22 | static 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 | ||
28 | static inline unsigned packet_length(const struct sk_buff *skb) | 29 | static 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 | ||
86 | struct net_bridge | 89 | struct 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 | } |
144 | static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); | 144 | static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); |
145 | 145 | ||
146 | static 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 | } | ||
151 | static 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 | } | ||
159 | static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR, | ||
160 | show_hairpin_mode, store_hairpin_mode); | ||
161 | |||
146 | static struct brport_attribute *brport_attrs[] = { | 162 | static 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; |