From 00f288224b000df09a01811b5f677bed18d0f75f Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 9 Oct 2012 09:48:41 +0100 Subject: [PATCH] --- yaml --- r: 334017 b: refs/heads/master c: 922cd657c95fe3e4214d68a958e98288b7a55bba h: refs/heads/master i: 334015: 5d939922c2ca9427129ac085c2716a013273ce58 v: v3 --- [refs] | 2 +- trunk/drivers/isdn/i4l/isdn_ppp.c | 2 +- trunk/drivers/net/vxlan.c | 148 ++++--------------- trunk/drivers/net/xen-netback/netback.c | 40 +---- trunk/include/linux/can/Kbuild | 5 - trunk/include/linux/if_link.h | 6 - trunk/include/linux/of_mdio.h | 20 +-- trunk/include/uapi/linux/can/Kbuild | 5 + trunk/include/{ => uapi}/linux/can/bcm.h | 0 trunk/include/{ => uapi}/linux/can/error.h | 0 trunk/include/{ => uapi}/linux/can/gw.h | 0 trunk/include/{ => uapi}/linux/can/netlink.h | 0 trunk/include/{ => uapi}/linux/can/raw.h | 0 trunk/net/bridge/br_netfilter.c | 3 - trunk/net/core/pktgen.c | 146 ++++++++++++++---- trunk/net/ipv4/route.c | 2 +- 16 files changed, 170 insertions(+), 209 deletions(-) rename trunk/include/{ => uapi}/linux/can/bcm.h (100%) rename trunk/include/{ => uapi}/linux/can/error.h (100%) rename trunk/include/{ => uapi}/linux/can/gw.h (100%) rename trunk/include/{ => uapi}/linux/can/netlink.h (100%) rename trunk/include/{ => uapi}/linux/can/raw.h (100%) diff --git a/[refs] b/[refs] index 6c99e86bc90d..4c40b3ef8322 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 68aaed54e7682aef261d5c2cf99e85a9dbf33a84 +refs/heads/master: 922cd657c95fe3e4214d68a958e98288b7a55bba diff --git a/trunk/drivers/isdn/i4l/isdn_ppp.c b/trunk/drivers/isdn/i4l/isdn_ppp.c index 61d78fa03b1a..a1e760150821 100644 --- a/trunk/drivers/isdn/i4l/isdn_ppp.c +++ b/trunk/drivers/isdn/i4l/isdn_ppp.c @@ -595,7 +595,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) j = ipc->num / (sizeof(long) * 8); i = ipc->num % (sizeof(long) * 8); if (j < 8) - protos[j] |= (1UL << i); + protos[j] |= (0x1 << i); ipc = ipc->next; } if ((r = set_arg(argp, protos, 8 * sizeof(long)))) diff --git a/trunk/drivers/net/vxlan.c b/trunk/drivers/net/vxlan.c index 607976c00162..8be9bf07bd39 100644 --- a/trunk/drivers/net/vxlan.c +++ b/trunk/drivers/net/vxlan.c @@ -106,8 +106,6 @@ struct vxlan_dev { __be32 gaddr; /* multicast group */ __be32 saddr; /* source address */ unsigned int link; /* link to multicast over */ - __u16 port_min; /* source port range */ - __u16 port_max; __u8 tos; /* TOS override */ __u8 ttl; bool learn; @@ -230,9 +228,9 @@ static u32 eth_hash(const unsigned char *addr) /* only want 6 bytes */ #ifdef __BIG_ENDIAN - value >>= 16; -#else value <<= 16; +#else + value >>= 16; #endif return hash_64(value, FDB_HASH_BITS); } @@ -537,6 +535,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) } __skb_pull(skb, sizeof(struct vxlanhdr)); + skb_postpull_rcsum(skb, eth_hdr(skb), sizeof(struct vxlanhdr)); /* Is this VNI defined? */ vni = ntohl(vxh->vx_vni) >> 8; @@ -555,6 +554,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) /* Re-examine inner Ethernet packet */ oip = ip_hdr(skb); skb->protocol = eth_type_trans(skb, vxlan->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); /* Ignore packet loops (and multicast echo) */ if (compare_ether_addr(eth_hdr(skb)->h_source, @@ -566,7 +566,6 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) __skb_tunnel_rx(skb, vxlan->dev); skb_reset_network_header(skb); - skb->ip_summed = CHECKSUM_NONE; err = IP_ECN_decapsulate(oip, skb); if (unlikely(err)) { @@ -622,89 +621,46 @@ static inline u8 vxlan_ecn_encap(u8 tos, return INET_ECN_encapsulate(tos, inner); } -static __be32 vxlan_find_dst(struct vxlan_dev *vxlan, struct sk_buff *skb) -{ - const struct ethhdr *eth = (struct ethhdr *) skb->data; - const struct vxlan_fdb *f; - - if (is_multicast_ether_addr(eth->h_dest)) - return vxlan->gaddr; - - f = vxlan_find_mac(vxlan, eth->h_dest); - if (f) - return f->remote_ip; - else - return vxlan->gaddr; - -} - -static void vxlan_sock_free(struct sk_buff *skb) -{ - sock_put(skb->sk); -} - -/* On transmit, associate with the tunnel socket */ -static void vxlan_set_owner(struct net_device *dev, struct sk_buff *skb) -{ - struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); - struct sock *sk = vn->sock->sk; - - skb_orphan(skb); - sock_hold(sk); - skb->sk = sk; - skb->destructor = vxlan_sock_free; -} - -/* Compute source port for outgoing packet - * first choice to use L4 flow hash since it will spread - * better and maybe available from hardware - * secondary choice is to use jhash on the Ethernet header - */ -static u16 vxlan_src_port(const struct vxlan_dev *vxlan, struct sk_buff *skb) -{ - unsigned int range = (vxlan->port_max - vxlan->port_min) + 1; - u32 hash; - - hash = skb_get_rxhash(skb); - if (!hash) - hash = jhash(skb->data, 2 * ETH_ALEN, - (__force u32) skb->protocol); - - return (((u64) hash * range) >> 32) + vxlan->port_min; -} - /* Transmit local packets over Vxlan * * Outer IP header inherits ECN and DF from inner header. * Outer UDP destination is the VXLAN assigned port. - * source port is based on hash of flow + * source port is based on hash of flow if available + * otherwise use a random value */ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); struct rtable *rt; + const struct ethhdr *eth; const struct iphdr *old_iph; struct iphdr *iph; struct vxlanhdr *vxh; struct udphdr *uh; struct flowi4 fl4; + struct vxlan_fdb *f; unsigned int pkt_len = skb->len; + u32 hash; __be32 dst; - __u16 src_port; __be16 df = 0; __u8 tos, ttl; int err; - dst = vxlan_find_dst(vxlan, skb); - if (!dst) - goto drop; - /* Need space for new headers (invalidates iph ptr) */ if (skb_cow_head(skb, VXLAN_HEADROOM)) goto drop; + eth = (void *)skb->data; old_iph = ip_hdr(skb); + if (!is_multicast_ether_addr(eth->h_dest) && + (f = vxlan_find_mac(vxlan, eth->h_dest))) + dst = f->remote_ip; + else if (vxlan->gaddr) { + dst = vxlan->gaddr; + } else + goto drop; + ttl = vxlan->ttl; if (!ttl && IN_MULTICAST(ntohl(dst))) ttl = 1; @@ -713,15 +669,11 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) if (tos == 1) tos = vxlan_get_dsfield(old_iph, skb); - src_port = vxlan_src_port(vxlan, skb); - - memset(&fl4, 0, sizeof(fl4)); - fl4.flowi4_oif = vxlan->link; - fl4.flowi4_tos = RT_TOS(tos); - fl4.daddr = dst; - fl4.saddr = vxlan->saddr; + hash = skb_get_rxhash(skb); - rt = ip_route_output_key(dev_net(dev), &fl4); + rt = ip_route_output_gre(dev_net(dev), &fl4, dst, + vxlan->saddr, vxlan->vni, + RT_TOS(tos), vxlan->link); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to %pI4\n", &dst); dev->stats.tx_carrier_errors++; @@ -750,7 +702,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) uh = udp_hdr(skb); uh->dest = htons(vxlan_port); - uh->source = htons(src_port); + uh->source = hash ? :random32(); uh->len = htons(skb->len); uh->check = 0; @@ -763,12 +715,10 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) iph->frag_off = df; iph->protocol = IPPROTO_UDP; iph->tos = vxlan_ecn_encap(tos, old_iph, skb); - iph->daddr = dst; + iph->daddr = fl4.daddr; iph->saddr = fl4.saddr; iph->ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); - vxlan_set_owner(dev, skb); - /* See __IPTUNNEL_XMIT */ skb->ip_summed = CHECKSUM_NONE; ip_select_ident(iph, &rt->dst, NULL); @@ -978,11 +928,9 @@ static void vxlan_setup(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); unsigned h; - int low, high; eth_hw_addr_random(dev); ether_setup(dev); - dev->hard_header_len = ETH_HLEN + VXLAN_HEADROOM; dev->netdev_ops = &vxlan_netdev_ops; dev->destructor = vxlan_free; @@ -999,10 +947,6 @@ static void vxlan_setup(struct net_device *dev) vxlan->age_timer.function = vxlan_cleanup; vxlan->age_timer.data = (unsigned long) vxlan; - inet_get_local_port_range(&low, &high); - vxlan->port_min = low; - vxlan->port_max = high; - vxlan->dev = dev; for (h = 0; h < FDB_HASH_SIZE; ++h) @@ -1019,7 +963,6 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 }, [IFLA_VXLAN_AGEING] = { .type = NLA_U32 }, [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 }, - [IFLA_VXLAN_PORT_RANGE] = { .len = sizeof(struct ifla_vxlan_port_range) }, }; static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) @@ -1052,18 +995,6 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) return -EADDRNOTAVAIL; } } - - if (data[IFLA_VXLAN_PORT_RANGE]) { - const struct ifla_vxlan_port_range *p - = nla_data(data[IFLA_VXLAN_PORT_RANGE]); - - if (ntohs(p->high) < ntohs(p->low)) { - pr_debug("port range %u .. %u not valid\n", - ntohs(p->low), ntohs(p->high)); - return -EINVAL; - } - } - return 0; } @@ -1090,18 +1021,14 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, if (data[IFLA_VXLAN_LOCAL]) vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]); - if (data[IFLA_VXLAN_LINK] && - (vxlan->link = nla_get_u32(data[IFLA_VXLAN_LINK]))) { - struct net_device *lowerdev - = __dev_get_by_index(net, vxlan->link); - - if (!lowerdev) { - pr_info("ifindex %d does not exist\n", vxlan->link); - return -ENODEV; - } + if (data[IFLA_VXLAN_LINK]) { + vxlan->link = nla_get_u32(data[IFLA_VXLAN_LINK]); - if (!tb[IFLA_MTU]) + if (!tb[IFLA_MTU]) { + struct net_device *lowerdev; + lowerdev = __dev_get_by_index(net, vxlan->link); dev->mtu = lowerdev->mtu - VXLAN_HEADROOM; + } } if (data[IFLA_VXLAN_TOS]) @@ -1118,13 +1045,6 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, if (data[IFLA_VXLAN_LIMIT]) vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]); - if (data[IFLA_VXLAN_PORT_RANGE]) { - const struct ifla_vxlan_port_range *p - = nla_data(data[IFLA_VXLAN_PORT_RANGE]); - vxlan->port_min = ntohs(p->low); - vxlan->port_max = ntohs(p->high); - } - err = register_netdevice(dev); if (!err) hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->vni)); @@ -1153,17 +1073,12 @@ static size_t vxlan_get_size(const struct net_device *dev) nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */ nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */ nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */ - nla_total_size(sizeof(struct ifla_vxlan_port_range)) + 0; } static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) { const struct vxlan_dev *vxlan = netdev_priv(dev); - struct ifla_vxlan_port_range ports = { - .low = htons(vxlan->port_min), - .high = htons(vxlan->port_max), - }; if (nla_put_u32(skb, IFLA_VXLAN_ID, vxlan->vni)) goto nla_put_failure; @@ -1184,9 +1099,6 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax)) goto nla_put_failure; - if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) - goto nla_put_failure; - return 0; nla_put_failure: diff --git a/trunk/drivers/net/xen-netback/netback.c b/trunk/drivers/net/xen-netback/netback.c index f2d6b78d901d..4ebfcf3d8a3b 100644 --- a/trunk/drivers/net/xen-netback/netback.c +++ b/trunk/drivers/net/xen-netback/netback.c @@ -335,35 +335,21 @@ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]); - unsigned long offset = skb_shinfo(skb)->frags[i].page_offset; unsigned long bytes; - - offset &= ~PAGE_MASK; - while (size > 0) { - BUG_ON(offset >= PAGE_SIZE); BUG_ON(copy_off > MAX_BUFFER_OFFSET); - bytes = PAGE_SIZE - offset; - - if (bytes > size) - bytes = size; - - if (start_new_rx_buffer(copy_off, bytes, 0)) { + if (start_new_rx_buffer(copy_off, size, 0)) { count++; copy_off = 0; } + bytes = size; if (copy_off + bytes > MAX_BUFFER_OFFSET) bytes = MAX_BUFFER_OFFSET - copy_off; copy_off += bytes; - - offset += bytes; size -= bytes; - - if (offset == PAGE_SIZE) - offset = 0; } } return count; @@ -417,24 +403,14 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, unsigned long bytes; /* Data must not cross a page boundary. */ - BUG_ON(size + offset > PAGE_SIZE< PAGE_SIZE); meta = npo->meta + npo->meta_prod - 1; - /* Skip unused frames from start of page */ - page += offset >> PAGE_SHIFT; - offset &= ~PAGE_MASK; - while (size > 0) { - BUG_ON(offset >= PAGE_SIZE); BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET); - bytes = PAGE_SIZE - offset; - - if (bytes > size) - bytes = size; - - if (start_new_rx_buffer(npo->copy_off, bytes, *head)) { + if (start_new_rx_buffer(npo->copy_off, size, *head)) { /* * Netfront requires there to be some data in the head * buffer. @@ -444,6 +420,7 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, meta = get_next_rx_buffer(vif, npo); } + bytes = size; if (npo->copy_off + bytes > MAX_BUFFER_OFFSET) bytes = MAX_BUFFER_OFFSET - npo->copy_off; @@ -476,13 +453,6 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, offset += bytes; size -= bytes; - /* Next frame */ - if (offset == PAGE_SIZE && size) { - BUG_ON(!PageCompound(page)); - page++; - offset = 0; - } - /* Leave a gap for the GSO descriptor. */ if (*head && skb_shinfo(skb)->gso_size && !vif->gso_prefix) vif->rx.req_cons++; diff --git a/trunk/include/linux/can/Kbuild b/trunk/include/linux/can/Kbuild index c62b7f1728f9..e69de29bb2d1 100644 --- a/trunk/include/linux/can/Kbuild +++ b/trunk/include/linux/can/Kbuild @@ -1,5 +0,0 @@ -header-y += raw.h -header-y += bcm.h -header-y += gw.h -header-y += error.h -header-y += netlink.h diff --git a/trunk/include/linux/if_link.h b/trunk/include/linux/if_link.h index 3265f332998a..e4dad4ddf085 100644 --- a/trunk/include/linux/if_link.h +++ b/trunk/include/linux/if_link.h @@ -284,16 +284,10 @@ enum { IFLA_VXLAN_LEARNING, IFLA_VXLAN_AGEING, IFLA_VXLAN_LIMIT, - IFLA_VXLAN_PORT_RANGE, __IFLA_VXLAN_MAX }; #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) -struct ifla_vxlan_port_range { - __be16 low; - __be16 high; -}; - /* SR-IOV virtual function management section */ enum { diff --git a/trunk/include/linux/of_mdio.h b/trunk/include/linux/of_mdio.h index 8163107b94b4..6ef49b803efb 100644 --- a/trunk/include/linux/of_mdio.h +++ b/trunk/include/linux/of_mdio.h @@ -26,32 +26,32 @@ extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np); #else /* CONFIG_OF */ -static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) +int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) { return -ENOSYS; } -static inline struct phy_device *of_phy_find_device(struct device_node *phy_np) +struct phy_device *of_phy_find_device(struct device_node *phy_np) { return NULL; } -static inline struct phy_device *of_phy_connect(struct net_device *dev, - struct device_node *phy_np, - void (*hndlr)(struct net_device *), - u32 flags, phy_interface_t iface) +struct phy_device *of_phy_connect(struct net_device *dev, + struct device_node *phy_np, + void (*hndlr)(struct net_device *), + u32 flags, phy_interface_t iface) { return NULL; } -static inline struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, - void (*hndlr)(struct net_device *), - phy_interface_t iface) +struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, + void (*hndlr)(struct net_device *), + phy_interface_t iface) { return NULL; } -static inline struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np) +struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np) { return NULL; } diff --git a/trunk/include/uapi/linux/can/Kbuild b/trunk/include/uapi/linux/can/Kbuild index aafaa5aa54d4..21c91bf25a29 100644 --- a/trunk/include/uapi/linux/can/Kbuild +++ b/trunk/include/uapi/linux/can/Kbuild @@ -1 +1,6 @@ # UAPI Header export list +header-y += bcm.h +header-y += error.h +header-y += gw.h +header-y += netlink.h +header-y += raw.h diff --git a/trunk/include/linux/can/bcm.h b/trunk/include/uapi/linux/can/bcm.h similarity index 100% rename from trunk/include/linux/can/bcm.h rename to trunk/include/uapi/linux/can/bcm.h diff --git a/trunk/include/linux/can/error.h b/trunk/include/uapi/linux/can/error.h similarity index 100% rename from trunk/include/linux/can/error.h rename to trunk/include/uapi/linux/can/error.h diff --git a/trunk/include/linux/can/gw.h b/trunk/include/uapi/linux/can/gw.h similarity index 100% rename from trunk/include/linux/can/gw.h rename to trunk/include/uapi/linux/can/gw.h diff --git a/trunk/include/linux/can/netlink.h b/trunk/include/uapi/linux/can/netlink.h similarity index 100% rename from trunk/include/linux/can/netlink.h rename to trunk/include/uapi/linux/can/netlink.h diff --git a/trunk/include/linux/can/raw.h b/trunk/include/uapi/linux/can/raw.h similarity index 100% rename from trunk/include/linux/can/raw.h rename to trunk/include/uapi/linux/can/raw.h diff --git a/trunk/net/bridge/br_netfilter.c b/trunk/net/bridge/br_netfilter.c index fe43bc7b063f..68e8f364bbf8 100644 --- a/trunk/net/bridge/br_netfilter.c +++ b/trunk/net/bridge/br_netfilter.c @@ -265,9 +265,6 @@ static int br_parse_ip_options(struct sk_buff *skb) struct net_device *dev = skb->dev; u32 len; - if (!pskb_may_pull(skb, sizeof(struct iphdr))) - goto inhdr_error; - iph = ip_hdr(skb); opt = &(IPCB(skb)->opt); diff --git a/trunk/net/core/pktgen.c b/trunk/net/core/pktgen.c index d1dc14c2aac4..148e73d2c451 100644 --- a/trunk/net/core/pktgen.c +++ b/trunk/net/core/pktgen.c @@ -248,8 +248,8 @@ struct pktgen_dev { int removal_mark; /* non-zero => the device is marked for * removal by worker thread */ - int min_pkt_size; - int max_pkt_size; + int min_pkt_size; /* = ETH_ZLEN; */ + int max_pkt_size; /* = ETH_ZLEN; */ int pkt_overhead; /* overhead for MPLS, VLANs, IPSEC etc */ int nfrags; struct page *page; @@ -449,6 +449,8 @@ static void pktgen_stop_all_threads_ifs(void); static void pktgen_stop(struct pktgen_thread *t); static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); +static unsigned int scan_ip6(const char *s, char ip[16]); + /* Module parameters, defaults. */ static int pg_count_d __read_mostly = 1000; static int pg_delay_d __read_mostly; @@ -700,8 +702,8 @@ static int pktgen_if_show(struct seq_file *seq, void *v) &pkt_dev->cur_in6_saddr, &pkt_dev->cur_in6_daddr); } else - seq_printf(seq, " cur_saddr: %pI4 cur_daddr: %pI4\n", - &pkt_dev->cur_saddr, &pkt_dev->cur_daddr); + seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n", + pkt_dev->cur_saddr, pkt_dev->cur_daddr); seq_printf(seq, " cur_udp_dst: %d cur_udp_src: %d\n", pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src); @@ -1297,7 +1299,7 @@ static ssize_t pktgen_if_write(struct file *file, return -EFAULT; buf[len] = 0; - in6_pton(buf, -1, pkt_dev->in6_daddr.s6_addr, -1, NULL); + scan_ip6(buf, pkt_dev->in6_daddr.s6_addr); snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_daddr); pkt_dev->cur_in6_daddr = pkt_dev->in6_daddr; @@ -1320,7 +1322,7 @@ static ssize_t pktgen_if_write(struct file *file, return -EFAULT; buf[len] = 0; - in6_pton(buf, -1, pkt_dev->min_in6_daddr.s6_addr, -1, NULL); + scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_daddr); pkt_dev->cur_in6_daddr = pkt_dev->min_in6_daddr; @@ -1342,7 +1344,7 @@ static ssize_t pktgen_if_write(struct file *file, return -EFAULT; buf[len] = 0; - in6_pton(buf, -1, pkt_dev->max_in6_daddr.s6_addr, -1, NULL); + scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_daddr); if (debug) @@ -1363,7 +1365,7 @@ static ssize_t pktgen_if_write(struct file *file, return -EFAULT; buf[len] = 0; - in6_pton(buf, -1, pkt_dev->in6_saddr.s6_addr, -1, NULL); + scan_ip6(buf, pkt_dev->in6_saddr.s6_addr); snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_saddr); pkt_dev->cur_in6_saddr = pkt_dev->in6_saddr; @@ -2034,17 +2036,19 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) /* Set up Dest MAC */ memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); + /* Set up pkt size */ + pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size; + if (pkt_dev->flags & F_IPV6) { + /* + * Skip this automatic address setting until locks or functions + * gets exported + */ + +#ifdef NOTNOW int i, set = 0, err = 1; struct inet6_dev *idev; - if (pkt_dev->min_pkt_size == 0) { - pkt_dev->min_pkt_size = 14 + sizeof(struct ipv6hdr) - + sizeof(struct udphdr) - + sizeof(struct pktgen_hdr) - + pkt_dev->pkt_overhead; - } - for (i = 0; i < IN6_ADDR_HSIZE; i++) if (pkt_dev->cur_in6_saddr.s6_addr[i]) { set = 1; @@ -2065,8 +2069,9 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) struct inet6_ifaddr *ifp; read_lock_bh(&idev->lock); - list_for_each_entry(ifp, &idev->addr_list, if_list) { - if ((ifp->scope & IFA_LINK) && + for (ifp = idev->addr_list; ifp; + ifp = ifp->if_next) { + if (ifp->scope == IFA_LINK && !(ifp->flags & IFA_F_TENTATIVE)) { pkt_dev->cur_in6_saddr = ifp->addr; err = 0; @@ -2079,14 +2084,8 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) if (err) pr_err("ERROR: IPv6 link address not available\n"); } +#endif } else { - if (pkt_dev->min_pkt_size == 0) { - pkt_dev->min_pkt_size = 14 + sizeof(struct iphdr) - + sizeof(struct udphdr) - + sizeof(struct pktgen_hdr) - + pkt_dev->pkt_overhead; - } - pkt_dev->saddr_min = 0; pkt_dev->saddr_max = 0; if (strlen(pkt_dev->src_min) == 0) { @@ -2112,10 +2111,6 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) pkt_dev->daddr_max = in_aton(pkt_dev->dst_max); } /* Initialize current values. */ - pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size; - if (pkt_dev->min_pkt_size > pkt_dev->max_pkt_size) - pkt_dev->max_pkt_size = pkt_dev->min_pkt_size; - pkt_dev->cur_dst_mac_offset = 0; pkt_dev->cur_src_mac_offset = 0; pkt_dev->cur_saddr = pkt_dev->saddr_min; @@ -2763,6 +2758,97 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, return skb; } +/* + * scan_ip6, fmt_ip taken from dietlibc-0.21 + * Author Felix von Leitner + * + * Slightly modified for kernel. + * Should be candidate for net/ipv4/utils.c + * --ro + */ + +static unsigned int scan_ip6(const char *s, char ip[16]) +{ + unsigned int i; + unsigned int len = 0; + unsigned long u; + char suffix[16]; + unsigned int prefixlen = 0; + unsigned int suffixlen = 0; + __be32 tmp; + char *pos; + + for (i = 0; i < 16; i++) + ip[i] = 0; + + for (;;) { + if (*s == ':') { + len++; + if (s[1] == ':') { /* Found "::", skip to part 2 */ + s += 2; + len++; + break; + } + s++; + } + + u = simple_strtoul(s, &pos, 16); + i = pos - s; + if (!i) + return 0; + if (prefixlen == 12 && s[i] == '.') { + + /* the last 4 bytes may be written as IPv4 address */ + + tmp = in_aton(s); + memcpy((struct in_addr *)(ip + 12), &tmp, sizeof(tmp)); + return i + len; + } + ip[prefixlen++] = (u >> 8); + ip[prefixlen++] = (u & 255); + s += i; + len += i; + if (prefixlen == 16) + return len; + } + +/* part 2, after "::" */ + for (;;) { + if (*s == ':') { + if (suffixlen == 0) + break; + s++; + len++; + } else if (suffixlen != 0) + break; + + u = simple_strtol(s, &pos, 16); + i = pos - s; + if (!i) { + if (*s) + len--; + break; + } + if (suffixlen + prefixlen <= 12 && s[i] == '.') { + tmp = in_aton(s); + memcpy((struct in_addr *)(suffix + suffixlen), &tmp, + sizeof(tmp)); + suffixlen += 4; + len += strlen(s); + break; + } + suffix[suffixlen++] = (u >> 8); + suffix[suffixlen++] = (u & 255); + s += i; + len += i; + if (prefixlen + suffixlen == 16) + break; + } + for (i = 0; i < suffixlen; i++) + ip[16 - suffixlen + i] = suffix[i]; + return len; +} + static struct sk_buff *fill_packet_ipv6(struct net_device *odev, struct pktgen_dev *pkt_dev) { @@ -2841,7 +2927,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, sizeof(struct ipv6hdr) - sizeof(struct udphdr) - pkt_dev->pkt_overhead; - if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) { + if (datalen < sizeof(struct pktgen_hdr)) { datalen = sizeof(struct pktgen_hdr); net_info_ratelimited("increased datalen to %d\n", datalen); } @@ -3462,6 +3548,8 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) } pkt_dev->removal_mark = 0; + pkt_dev->min_pkt_size = ETH_ZLEN; + pkt_dev->max_pkt_size = ETH_ZLEN; pkt_dev->nfrags = 0; pkt_dev->delay = pg_delay_d; pkt_dev->count = pg_count_d; diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 432f4bb77238..1a0da8dc8180 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -2220,7 +2220,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, goto nla_put_failure; if (fl4->flowi4_mark && - nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark)) + nla_put_be32(skb, RTA_MARK, fl4->flowi4_mark)) goto nla_put_failure; error = rt->dst.error;