[PATCH net-next v5 2/2] gtp: support SGSN-side tunnels
The GTP-tunnel driver is explicitly GGSN-side as it searches for PDP contexts based on the incoming packets _destination_ address. If we want to place ourselves on the SGSN side of the tunnel, then we want to be identifying PDP contexts based on _source_ address. Let it be noted that in a "real" configuration this module would never be used: the SGSN normally does not see IP packets as input. The justification for this functionality is for PGW load-testing applications where the input to the SGSN is locally generally IP traffic. This patch adds a "role" argument at GTP-link creation time to specify whether we are on the GGSN or SGSN side of the tunnel; this flag is then used to determine which part of the IP packet to use in determining the PDP context. Signed-off-by: Jonas Bonn <jo...@southpole.se> Acked-by: Pablo Neira Ayuso <pa...@netfilter.org> Acked-by: Harald Welte <lafo...@gnumonks.org> --- drivers/net/gtp.c| 42 ++ include/uapi/linux/if_link.h | 7 +++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 1f6d911..4fea1b3 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -74,6 +74,7 @@ struct gtp_dev { struct net_device *dev; + unsigned introle; unsigned inthash_size; struct hlist_head *tid_hash; struct hlist_head *addr_hash; @@ -154,8 +155,8 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr) return NULL; } -static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, - unsigned int hdrlen) +static bool gtp_check_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, + unsigned int hdrlen, unsigned int role) { struct iphdr *iph; @@ -164,27 +165,31 @@ static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, iph = (struct iphdr *)(skb->data + hdrlen); - return iph->saddr == pctx->ms_addr_ip4.s_addr; + if (role == GTP_ROLE_SGSN) + return iph->daddr == pctx->ms_addr_ip4.s_addr; + else + return iph->saddr == pctx->ms_addr_ip4.s_addr; } -/* Check if the inner IP source address in this packet is assigned to any +/* Check if the inner IP address in this packet is assigned to any * existing mobile subscriber. */ -static bool gtp_check_src_ms(struct sk_buff *skb, struct pdp_ctx *pctx, -unsigned int hdrlen) +static bool gtp_check_ms(struct sk_buff *skb, struct pdp_ctx *pctx, +unsigned int hdrlen, unsigned int role) { switch (ntohs(skb->protocol)) { case ETH_P_IP: - return gtp_check_src_ms_ipv4(skb, pctx, hdrlen); + return gtp_check_ms_ipv4(skb, pctx, hdrlen, role); } return false; } -static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen) +static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, + unsigned int hdrlen, unsigned int role) { struct pcpu_sw_netstats *stats; - if (!gtp_check_src_ms(skb, pctx, hdrlen)) { + if (!gtp_check_ms(skb, pctx, hdrlen, role)) { netdev_dbg(pctx->dev, "No PDP ctx for this MS\n"); return 1; } @@ -239,7 +244,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) return 1; } - return gtp_rx(pctx, skb, hdrlen); + return gtp_rx(pctx, skb, hdrlen, gtp->role); } static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) @@ -281,7 +286,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) return 1; } - return gtp_rx(pctx, skb, hdrlen); + return gtp_rx(pctx, skb, hdrlen, gtp->role); } static void gtp_encap_destroy(struct sock *sk) @@ -481,7 +486,11 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, * Prepend PDP header with TEI/TID from PDP ctx. */ iph = ip_hdr(skb); - pctx = ipv4_pdp_find(gtp, iph->daddr); + if (gtp->role == GTP_ROLE_SGSN) + pctx = ipv4_pdp_find(gtp, iph->saddr); + else + pctx = ipv4_pdp_find(gtp, iph->daddr); + if (!pctx) { netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n", >daddr); @@ -685,6 +694,7 @@ static const struct nla_policy gtp_policy[IFLA_GTP_MAX + 1] = { [IFLA_GTP_FD0] = { .type = NLA_U32 }, [IFLA_GTP_FD1] = { .type = NLA_U32 }, [IFLA_GTP_PDP_HASHSIZE] = { .type = NLA_U32 }, + [IFLA_GTP_ROLE] = { .type = NLA_U32 },
[PATCH net-next v5 1/2] gtp: rename SGSN netlink attribute
This is a mostly cosmetic rename of the SGSN netlink attribute to the GTP link. The justification for this is that we will be making the module support decapsulation of "downstream" SGSN packets, in which case the netlink parameter actually refers to the upstream GGSN peer. Renaming the parameter makes the relationship clearer. The legacy name is maintained as a define in the header file in order to not break existing code. Signed-off-by: Jonas Bonn <jo...@southpole.se> Acked-by: Pablo Neira Ayuso <pa...@netfilter.org> Acked-by: Harald Welte <lafo...@gnumonks.org> --- drivers/net/gtp.c| 22 +++--- include/uapi/linux/gtp.h | 3 ++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 3e1854f..1f6d911 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -56,7 +56,7 @@ struct pdp_ctx { u16 af; struct in_addr ms_addr_ip4; - struct in_addr sgsn_addr_ip4; + struct in_addr peer_addr_ip4; struct sock *sk; struct net_device *dev; @@ -489,17 +489,17 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, } netdev_dbg(dev, "found PDP context %p\n", pctx); - rt = ip4_route_output_gtp(, pctx->sk, pctx->sgsn_addr_ip4.s_addr); + rt = ip4_route_output_gtp(, pctx->sk, pctx->peer_addr_ip4.s_addr); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to SSGN %pI4\n", - >sgsn_addr_ip4.s_addr); + >peer_addr_ip4.s_addr); dev->stats.tx_carrier_errors++; goto err; } if (rt->dst.dev == dev) { netdev_dbg(dev, "circular route to SSGN %pI4\n", - >sgsn_addr_ip4.s_addr); + >peer_addr_ip4.s_addr); dev->stats.collisions++; goto err_rt; } @@ -866,8 +866,8 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) { pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); pctx->af = AF_INET; - pctx->sgsn_addr_ip4.s_addr = - nla_get_be32(info->attrs[GTPA_SGSN_ADDRESS]); + pctx->peer_addr_ip4.s_addr = + nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); pctx->ms_addr_ip4.s_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); @@ -957,13 +957,13 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk, switch (pctx->gtp_version) { case GTP_V0: netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI4 ms=%pI4 (pdp=%p)\n", - pctx->u.v0.tid, >sgsn_addr_ip4, + pctx->u.v0.tid, >peer_addr_ip4, >ms_addr_ip4, pctx); break; case GTP_V1: netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI4 ms=%pI4 (pdp=%p)\n", pctx->u.v1.i_tei, pctx->u.v1.o_tei, - >sgsn_addr_ip4, >ms_addr_ip4, pctx); + >peer_addr_ip4, >ms_addr_ip4, pctx); break; } @@ -994,7 +994,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[GTPA_VERSION] || !info->attrs[GTPA_LINK] || - !info->attrs[GTPA_SGSN_ADDRESS] || + !info->attrs[GTPA_PEER_ADDRESS] || !info->attrs[GTPA_MS_ADDRESS]) return -EINVAL; @@ -1126,7 +1126,7 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, goto nlmsg_failure; if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) || - nla_put_be32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr_ip4.s_addr) || + nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr) || nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr)) goto nla_put_failure; @@ -1237,7 +1237,7 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { [GTPA_LINK] = { .type = NLA_U32, }, [GTPA_VERSION] = { .type = NLA_U32, }, [GTPA_TID] = { .type = NLA_U64, }, - [GTPA_SGSN_ADDRESS] = { .type = NLA_U32, }, + [GTPA_PEER_ADDRESS] = { .type = NLA_U32, }, [GTPA_MS_ADDRESS] = { .type = NLA_U32, }, [GTPA_FLOW] = { .type = NLA_U16, }, [GTPA_NET_NS_FD]= { .type = NLA_U32, }, diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index 72a04a0..57d1edb 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -19,7 +19,8 @@
[PATCH net-next v5 0/2] GTP SGSN-side tunnel
Changes since v4: * Respin the series on top of net-next; the conflicts were trivial, amounting to just code having been shifted about Jonas Bonn (2): gtp: rename SGSN netlink attribute gtp: support SGSN-side tunnels drivers/net/gtp.c| 64 include/uapi/linux/gtp.h | 3 ++- include/uapi/linux/if_link.h | 7 + 3 files changed, 50 insertions(+), 24 deletions(-) -- 2.9.3
Re: [PATCH net-next v3 0/2] GTP SGSN-side tunnels
On 03/24/2017 11:41 AM, Pablo Neira Ayuso wrote: On Fri, Mar 24, 2017 at 10:33:56AM +0100, Jonas Bonn wrote: Changes since v2: * Move #define of legacy netlink attribute into enum * Added note to commit message about load-testing use-case * Ack from Pablo Thanks a lot Jonas! David, please apply. Thanks! David, please apply v4 instead as it has a coding-style fixup requested by Harald. Thanks, Jonas
[PATCH net-next v4 2/2] gtp: support SGSN-side tunnels
The GTP-tunnel driver is explicitly GGSN-side as it searches for PDP contexts based on the incoming packets _destination_ address. If we want to place ourselves on the SGSN side of the tunnel, then we want to be identifying PDP contexts based on _source_ address. Let it be noted that in a "real" configuration this module would never be used: the SGSN normally does not see IP packets as input. The justification for this functionality is for PGW load-testing applications where the input to the SGSN is locally generally IP traffic. This patch adds a "role" argument at GTP-link creation time to specify whether we are on the GGSN or SGSN side of the tunnel; this flag is then used to determine which part of the IP packet to use in determining the PDP context. Signed-off-by: Jonas Bonn <jo...@southpole.se> Acked-by: Pablo Neira Ayuso <pa...@netfilter.org> Acked-by: Harald Welte <lafo...@gnumonks.org> --- drivers/net/gtp.c| 40 ++-- include/uapi/linux/if_link.h | 7 +++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 3806be6..e674cb1 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -72,6 +72,7 @@ struct gtp_dev { struct net *net; struct net_device *dev; + unsigned introle; unsigned inthash_size; struct hlist_head *tid_hash; struct hlist_head *addr_hash; @@ -150,8 +151,8 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr) return NULL; } -static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, - unsigned int hdrlen) +static bool gtp_check_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, + unsigned int hdrlen, unsigned int role) { struct iphdr *iph; @@ -160,18 +161,21 @@ static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, iph = (struct iphdr *)(skb->data + hdrlen); - return iph->saddr == pctx->ms_addr_ip4.s_addr; + if (role == GTP_ROLE_SGSN) + return iph->daddr == pctx->ms_addr_ip4.s_addr; + else + return iph->saddr == pctx->ms_addr_ip4.s_addr; } -/* Check if the inner IP source address in this packet is assigned to any +/* Check if the inner IP address in this packet is assigned to any * existing mobile subscriber. */ -static bool gtp_check_src_ms(struct sk_buff *skb, struct pdp_ctx *pctx, -unsigned int hdrlen) +static bool gtp_check_ms(struct sk_buff *skb, struct pdp_ctx *pctx, +unsigned int hdrlen, unsigned int role) { switch (ntohs(skb->protocol)) { case ETH_P_IP: - return gtp_check_src_ms_ipv4(skb, pctx, hdrlen); + return gtp_check_ms_ipv4(skb, pctx, hdrlen, role); } return false; } @@ -205,7 +209,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb, goto out_rcu; } - if (!gtp_check_src_ms(skb, pctx, hdrlen)) { + if (!gtp_check_ms(skb, pctx, hdrlen, gtp->role)) { netdev_dbg(gtp->dev, "No PDP ctx for this MS\n"); ret = -1; goto out_rcu; @@ -262,7 +266,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb, goto out_rcu; } - if (!gtp_check_src_ms(skb, pctx, hdrlen)) { + if (!gtp_check_ms(skb, pctx, hdrlen, gtp->role)) { netdev_dbg(gtp->dev, "No PDP ctx for this MS\n"); ret = -1; goto out_rcu; @@ -491,7 +495,11 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, * Prepend PDP header with TEI/TID from PDP ctx. */ iph = ip_hdr(skb); - pctx = ipv4_pdp_find(gtp, iph->daddr); + if (gtp->role == GTP_ROLE_SGSN) + pctx = ipv4_pdp_find(gtp, iph->saddr); + else + pctx = ipv4_pdp_find(gtp, iph->daddr); + if (!pctx) { netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n", >daddr); @@ -666,12 +674,23 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, int hashsize, err, fd0, fd1; struct gtp_dev *gtp; struct gtp_net *gn; + unsigned int role; + + if (data[IFLA_GTP_ROLE]) { + role = nla_get_u32(data[IFLA_GTP_ROLE]); + if (role > GTP_ROLE_SGSN) + return -EINVAL; + } else { + role = GTP_ROLE_GGSN; + } if (!data[IFLA_GTP_FD0] || !data[IFLA_GTP_FD1]) return -EINVAL; gtp = netdev_priv(dev); + gtp->role = role;
[PATCH net-next v4 1/2] gtp: rename SGSN netlink attribute
This is a mostly cosmetic rename of the SGSN netlink attribute to the GTP link. The justification for this is that we will be making the module support decapsulation of "downstream" SGSN packets, in which case the netlink parameter actually refers to the upstream GGSN peer. Renaming the parameter makes the relationship clearer. The legacy name is maintained as a define in the header file in order to not break existing code. Signed-off-by: Jonas Bonn <jo...@southpole.se> Acked-by: Pablo Neira Ayuso <pa...@netfilter.org> Acked-by: Harald Welte <lafo...@gnumonks.org> --- drivers/net/gtp.c| 22 +++--- include/uapi/linux/gtp.h | 3 ++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 50349a9..3806be6 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -56,7 +56,7 @@ struct pdp_ctx { u16 af; struct in_addr ms_addr_ip4; - struct in_addr sgsn_addr_ip4; + struct in_addr peer_addr_ip4; atomic_ttx_seq; struct rcu_head rcu_head; @@ -522,17 +522,17 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, } rt = ip4_route_output_gtp(sock_net(sk), , gtp->sock0->sk, - pctx->sgsn_addr_ip4.s_addr); + pctx->peer_addr_ip4.s_addr); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to SSGN %pI4\n", - >sgsn_addr_ip4.s_addr); + >peer_addr_ip4.s_addr); dev->stats.tx_carrier_errors++; goto err; } if (rt->dst.dev == dev) { netdev_dbg(dev, "circular route to SSGN %pI4\n", - >sgsn_addr_ip4.s_addr); + >peer_addr_ip4.s_addr); dev->stats.collisions++; goto err_rt; } @@ -894,8 +894,8 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) { pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); pctx->af = AF_INET; - pctx->sgsn_addr_ip4.s_addr = - nla_get_be32(info->attrs[GTPA_SGSN_ADDRESS]); + pctx->peer_addr_ip4.s_addr = + nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); pctx->ms_addr_ip4.s_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); @@ -981,13 +981,13 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) switch (pctx->gtp_version) { case GTP_V0: netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI4 ms=%pI4 (pdp=%p)\n", - pctx->u.v0.tid, >sgsn_addr_ip4, + pctx->u.v0.tid, >peer_addr_ip4, >ms_addr_ip4, pctx); break; case GTP_V1: netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI4 ms=%pI4 (pdp=%p)\n", pctx->u.v1.i_tei, pctx->u.v1.o_tei, - >sgsn_addr_ip4, >ms_addr_ip4, pctx); + >peer_addr_ip4, >ms_addr_ip4, pctx); break; } @@ -1001,7 +1001,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[GTPA_VERSION] || !info->attrs[GTPA_LINK] || - !info->attrs[GTPA_SGSN_ADDRESS] || + !info->attrs[GTPA_PEER_ADDRESS] || !info->attrs[GTPA_MS_ADDRESS]) return -EINVAL; @@ -1114,7 +1114,7 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, goto nlmsg_failure; if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) || - nla_put_be32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr_ip4.s_addr) || + nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr) || nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr)) goto nla_put_failure; @@ -1267,7 +1267,7 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { [GTPA_LINK] = { .type = NLA_U32, }, [GTPA_VERSION] = { .type = NLA_U32, }, [GTPA_TID] = { .type = NLA_U64, }, - [GTPA_SGSN_ADDRESS] = { .type = NLA_U32, }, + [GTPA_PEER_ADDRESS] = { .type = NLA_U32, }, [GTPA_MS_ADDRESS] = { .type = NLA_U32, }, [GTPA_FLOW] = { .type = NLA_U16, }, [GTPA_NET_NS_FD]= { .type = NLA_U32, }, diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index 72a04a0..57d1edb 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -19,7 +19,8 @@ en
[PATCH net-next v4 0/2] GTP SGSN-side tunnels
Changes from v3: * Coding style fixup: remove extraneous braces on if-statement * Ack from Harald Jonas Bonn (2): gtp: rename SGSN netlink attribute gtp: support SGSN-side tunnels drivers/net/gtp.c| 62 +--- include/uapi/linux/gtp.h | 3 ++- include/uapi/linux/if_link.h | 7 + 3 files changed, 50 insertions(+), 22 deletions(-) -- 2.9.3
Re: [PATCH net-next v3 0/2] GTP SGSN-side tunnels
Hi Harald, On 03/24/2017 11:15 AM, Harald Welte wrote: Hi Jonas, looks fine to me, but I haven't tested it. Did you manually test it using the extended libgtpnl + tools? I have tested it against your libgtpnl branch laforge/sgsn-role. Creating an interface with tools/gtp-link works fine. We have been running the v1 patches in a production load-testing system for the last month. That all works and gives good performance. I haven't been able to actually run the v2 and v3 patches in that environment as access to it is a bit limited... that said, the changes from v1 to v3 are really only cosmetic and don't even touch the "parts that matter" with respect to encapsulation. Really the patch is pretty trivial... mucking about with the netlink interface is the bulk of it and that bit has been tested and works. Also, in code like this: in + if (gtp->role == GTP_ROLE_SGSN) { + pctx = ipv4_pdp_find(gtp, iph->saddr); + } else { I think general Linux kernel coding style is to not have curly-brackets around single-line blocks. See "Do not unnecessarily use braces where a single statement will do." in line 169 of Documentation/process/coding-style.rst I won't mind your current style, and it is not a blocker issue to me, but still it would be nice for general consistency. OK, I'll fix that up just for the sake of correctness and send a v4. Acked-by: Harald WelteThanks, Jonas
[PATCH net-next v3 1/2] gtp: rename SGSN netlink attribute
This is a mostly cosmetic rename of the SGSN netlink attribute to the GTP link. The justification for this is that we will be making the module support decapsulation of "downstream" SGSN packets, in which case the netlink parameter actually refers to the upstream GGSN peer. Renaming the parameter makes the relationship clearer. The legacy name is maintained as a define in the header file in order to not break existing code. Signed-off-by: Jonas Bonn <jo...@southpole.se> Acked-by: Pablo Neira Ayuso <pa...@netfilter.org> --- drivers/net/gtp.c| 22 +++--- include/uapi/linux/gtp.h | 3 ++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 50349a9..3806be6 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -56,7 +56,7 @@ struct pdp_ctx { u16 af; struct in_addr ms_addr_ip4; - struct in_addr sgsn_addr_ip4; + struct in_addr peer_addr_ip4; atomic_ttx_seq; struct rcu_head rcu_head; @@ -522,17 +522,17 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, } rt = ip4_route_output_gtp(sock_net(sk), , gtp->sock0->sk, - pctx->sgsn_addr_ip4.s_addr); + pctx->peer_addr_ip4.s_addr); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to SSGN %pI4\n", - >sgsn_addr_ip4.s_addr); + >peer_addr_ip4.s_addr); dev->stats.tx_carrier_errors++; goto err; } if (rt->dst.dev == dev) { netdev_dbg(dev, "circular route to SSGN %pI4\n", - >sgsn_addr_ip4.s_addr); + >peer_addr_ip4.s_addr); dev->stats.collisions++; goto err_rt; } @@ -894,8 +894,8 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) { pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); pctx->af = AF_INET; - pctx->sgsn_addr_ip4.s_addr = - nla_get_be32(info->attrs[GTPA_SGSN_ADDRESS]); + pctx->peer_addr_ip4.s_addr = + nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); pctx->ms_addr_ip4.s_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); @@ -981,13 +981,13 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) switch (pctx->gtp_version) { case GTP_V0: netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI4 ms=%pI4 (pdp=%p)\n", - pctx->u.v0.tid, >sgsn_addr_ip4, + pctx->u.v0.tid, >peer_addr_ip4, >ms_addr_ip4, pctx); break; case GTP_V1: netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI4 ms=%pI4 (pdp=%p)\n", pctx->u.v1.i_tei, pctx->u.v1.o_tei, - >sgsn_addr_ip4, >ms_addr_ip4, pctx); + >peer_addr_ip4, >ms_addr_ip4, pctx); break; } @@ -1001,7 +1001,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[GTPA_VERSION] || !info->attrs[GTPA_LINK] || - !info->attrs[GTPA_SGSN_ADDRESS] || + !info->attrs[GTPA_PEER_ADDRESS] || !info->attrs[GTPA_MS_ADDRESS]) return -EINVAL; @@ -1114,7 +1114,7 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, goto nlmsg_failure; if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) || - nla_put_be32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr_ip4.s_addr) || + nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr) || nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr)) goto nla_put_failure; @@ -1267,7 +1267,7 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { [GTPA_LINK] = { .type = NLA_U32, }, [GTPA_VERSION] = { .type = NLA_U32, }, [GTPA_TID] = { .type = NLA_U64, }, - [GTPA_SGSN_ADDRESS] = { .type = NLA_U32, }, + [GTPA_PEER_ADDRESS] = { .type = NLA_U32, }, [GTPA_MS_ADDRESS] = { .type = NLA_U32, }, [GTPA_FLOW] = { .type = NLA_U16, }, [GTPA_NET_NS_FD]= { .type = NLA_U32, }, diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index 72a04a0..57d1edb 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -19,7 +19,8 @@ enum gtp_attrs { GTPA_LINK, GT
[PATCH net-next v3 2/2] gtp: support SGSN-side tunnels
The GTP-tunnel driver is explicitly GGSN-side as it searches for PDP contexts based on the incoming packets _destination_ address. If we want to place ourselves on the SGSN side of the tunnel, then we want to be identifying PDP contexts based on _source_ address. Let it be noted that in a "real" configuration this module would never be used: the SGSN normally does not see IP packets as input. The justification for this functionality is for PGW load-testing applications where the input to the SGSN is locally generally IP traffic. This patch adds a "role" argument at GTP-link creation time to specify whether we are on the GGSN or SGSN side of the tunnel; this flag is then used to determine which part of the IP packet to use in determining the PDP context. Signed-off-by: Jonas Bonn <jo...@southpole.se> Acked-by: Pablo Neira Ayuso <pa...@netfilter.org> --- drivers/net/gtp.c| 41 +++-- include/uapi/linux/if_link.h | 7 +++ 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 3806be6..b54d1a3 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -72,6 +72,7 @@ struct gtp_dev { struct net *net; struct net_device *dev; + unsigned introle; unsigned inthash_size; struct hlist_head *tid_hash; struct hlist_head *addr_hash; @@ -150,8 +151,8 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr) return NULL; } -static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, - unsigned int hdrlen) +static bool gtp_check_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, + unsigned int hdrlen, unsigned int role) { struct iphdr *iph; @@ -160,18 +161,22 @@ static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, iph = (struct iphdr *)(skb->data + hdrlen); - return iph->saddr == pctx->ms_addr_ip4.s_addr; + if (role == GTP_ROLE_SGSN) { + return iph->daddr == pctx->ms_addr_ip4.s_addr; + } else { + return iph->saddr == pctx->ms_addr_ip4.s_addr; + } } -/* Check if the inner IP source address in this packet is assigned to any +/* Check if the inner IP address in this packet is assigned to any * existing mobile subscriber. */ -static bool gtp_check_src_ms(struct sk_buff *skb, struct pdp_ctx *pctx, -unsigned int hdrlen) +static bool gtp_check_ms(struct sk_buff *skb, struct pdp_ctx *pctx, +unsigned int hdrlen, unsigned int role) { switch (ntohs(skb->protocol)) { case ETH_P_IP: - return gtp_check_src_ms_ipv4(skb, pctx, hdrlen); + return gtp_check_ms_ipv4(skb, pctx, hdrlen, role); } return false; } @@ -205,7 +210,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb, goto out_rcu; } - if (!gtp_check_src_ms(skb, pctx, hdrlen)) { + if (!gtp_check_ms(skb, pctx, hdrlen, gtp->role)) { netdev_dbg(gtp->dev, "No PDP ctx for this MS\n"); ret = -1; goto out_rcu; @@ -262,7 +267,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb, goto out_rcu; } - if (!gtp_check_src_ms(skb, pctx, hdrlen)) { + if (!gtp_check_ms(skb, pctx, hdrlen, gtp->role)) { netdev_dbg(gtp->dev, "No PDP ctx for this MS\n"); ret = -1; goto out_rcu; @@ -491,7 +496,11 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, * Prepend PDP header with TEI/TID from PDP ctx. */ iph = ip_hdr(skb); - pctx = ipv4_pdp_find(gtp, iph->daddr); + if (gtp->role == GTP_ROLE_SGSN) { + pctx = ipv4_pdp_find(gtp, iph->saddr); + } else { + pctx = ipv4_pdp_find(gtp, iph->daddr); + } if (!pctx) { netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n", >daddr); @@ -666,12 +675,23 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, int hashsize, err, fd0, fd1; struct gtp_dev *gtp; struct gtp_net *gn; + unsigned int role; + + if (data[IFLA_GTP_ROLE]) { + role = nla_get_u32(data[IFLA_GTP_ROLE]); + if (role > GTP_ROLE_SGSN) + return -EINVAL; + } else { + role = GTP_ROLE_GGSN; + } if (!data[IFLA_GTP_FD0] || !data[IFLA_GTP_FD1]) return -EINVAL; gtp = netdev_priv(dev); + gtp->role = role; + fd0 = nl
[PATCH net-next v3 0/2] GTP SGSN-side tunnels
Changes since v2: * Move #define of legacy netlink attribute into enum * Added note to commit message about load-testing use-case * Ack from Pablo Jonas Bonn (2): gtp: rename SGSN netlink attribute gtp: support SGSN-side tunnels drivers/net/gtp.c| 63 +--- include/uapi/linux/gtp.h | 3 ++- include/uapi/linux/if_link.h | 7 + 3 files changed, 51 insertions(+), 22 deletions(-) -- 2.9.3
Re: [PATCH 1/1] gtp: support SGSN-side tunnels
Hi Harald, On 03/15/2017 05:39 PM, Harald Welte wrote: Hi Jonas, are you working on the review feedback that was provided back in early February? I think there were some comments like * remove unrelated cosmetic change in comment * change from FLAGS to a dedicated MODE netlink attribute * add libgtpnl code and some usage information or even sample scripts I would definitely like to see this move forward, particularly in order to test the GGSN-side code. Sorry for the delay in this. I've sent, just now, revised patches to the kernel module. I was going to send some libgtpnl patches but I noticed, when gathering these up, that you have already made most of the necessary changes on a new branch. What you've got there is almost identical to what I've got. Since you used the terminology "role" instead of "mode" in your libgtpnl branch, I made the corresponding change in the kernel module, too, so it now calls this role instead of mode. Regards, Jonas Regards, Harald
[PATCH v2 2/2] gtp: support SGSN-side tunnels
The GTP-tunnel driver is explicitly GGSN-side as it searches for PDP contexts based on the incoming packets _destination_ address. If we want to write an SGSN, then we want to be idenityfing PDP contexts based on _source_ address. This patch adds a "role" argument at GTP-link creation time to specify whether we are on the GGSN or SGSN side of the tunnel; this flag is then used to determine which part of the IP packet to use in determining the PDP context. Signed-off-by: Jonas Bonn <jo...@southpole.se> --- drivers/net/gtp.c| 41 +++-- include/uapi/linux/if_link.h | 7 +++ 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 3806be6..b54d1a3 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -72,6 +72,7 @@ struct gtp_dev { struct net *net; struct net_device *dev; + unsigned introle; unsigned inthash_size; struct hlist_head *tid_hash; struct hlist_head *addr_hash; @@ -150,8 +151,8 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr) return NULL; } -static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, - unsigned int hdrlen) +static bool gtp_check_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, + unsigned int hdrlen, unsigned int role) { struct iphdr *iph; @@ -160,18 +161,22 @@ static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, iph = (struct iphdr *)(skb->data + hdrlen); - return iph->saddr == pctx->ms_addr_ip4.s_addr; + if (role == GTP_ROLE_SGSN) { + return iph->daddr == pctx->ms_addr_ip4.s_addr; + } else { + return iph->saddr == pctx->ms_addr_ip4.s_addr; + } } -/* Check if the inner IP source address in this packet is assigned to any +/* Check if the inner IP address in this packet is assigned to any * existing mobile subscriber. */ -static bool gtp_check_src_ms(struct sk_buff *skb, struct pdp_ctx *pctx, -unsigned int hdrlen) +static bool gtp_check_ms(struct sk_buff *skb, struct pdp_ctx *pctx, +unsigned int hdrlen, unsigned int role) { switch (ntohs(skb->protocol)) { case ETH_P_IP: - return gtp_check_src_ms_ipv4(skb, pctx, hdrlen); + return gtp_check_ms_ipv4(skb, pctx, hdrlen, role); } return false; } @@ -205,7 +210,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb, goto out_rcu; } - if (!gtp_check_src_ms(skb, pctx, hdrlen)) { + if (!gtp_check_ms(skb, pctx, hdrlen, gtp->role)) { netdev_dbg(gtp->dev, "No PDP ctx for this MS\n"); ret = -1; goto out_rcu; @@ -262,7 +267,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb, goto out_rcu; } - if (!gtp_check_src_ms(skb, pctx, hdrlen)) { + if (!gtp_check_ms(skb, pctx, hdrlen, gtp->role)) { netdev_dbg(gtp->dev, "No PDP ctx for this MS\n"); ret = -1; goto out_rcu; @@ -491,7 +496,11 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, * Prepend PDP header with TEI/TID from PDP ctx. */ iph = ip_hdr(skb); - pctx = ipv4_pdp_find(gtp, iph->daddr); + if (gtp->role == GTP_ROLE_SGSN) { + pctx = ipv4_pdp_find(gtp, iph->saddr); + } else { + pctx = ipv4_pdp_find(gtp, iph->daddr); + } if (!pctx) { netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n", >daddr); @@ -666,12 +675,23 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, int hashsize, err, fd0, fd1; struct gtp_dev *gtp; struct gtp_net *gn; + unsigned int role; + + if (data[IFLA_GTP_ROLE]) { + role = nla_get_u32(data[IFLA_GTP_ROLE]); + if (role > GTP_ROLE_SGSN) + return -EINVAL; + } else { + role = GTP_ROLE_GGSN; + } if (!data[IFLA_GTP_FD0] || !data[IFLA_GTP_FD1]) return -EINVAL; gtp = netdev_priv(dev); + gtp->role = role; + fd0 = nla_get_u32(data[IFLA_GTP_FD0]); fd1 = nla_get_u32(data[IFLA_GTP_FD1]); @@ -723,6 +743,7 @@ static const struct nla_policy gtp_policy[IFLA_GTP_MAX + 1] = { [IFLA_GTP_FD0] = { .type = NLA_U32 }, [IFLA_GTP_FD1] = { .type = NLA_U32 }, [IFLA_GTP_PDP_HASHSIZE] = { .type = NLA_U32 }, + [IFLA_GTP_
[PATCH v2 1/2] gtp: rename SGSN netlink attribute
This is a mostly cosmetic rename of the SGSN netlink attribute to the GTP link. The justification for this is that we will be making the module support decapsulation of "downstream" SGSN packets, in which case the netlink parameter actually refers to the upstream GGSN peer. Renaming the parameter makes the relationship clearer. The legacy name is maintained as a define in the header file in order to not break existing code. Signed-off-by: Jonas Bonn <jo...@southpole.se> --- drivers/net/gtp.c| 22 +++--- include/uapi/linux/gtp.h | 3 ++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 50349a9..3806be6 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -56,7 +56,7 @@ struct pdp_ctx { u16 af; struct in_addr ms_addr_ip4; - struct in_addr sgsn_addr_ip4; + struct in_addr peer_addr_ip4; atomic_ttx_seq; struct rcu_head rcu_head; @@ -522,17 +522,17 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, } rt = ip4_route_output_gtp(sock_net(sk), , gtp->sock0->sk, - pctx->sgsn_addr_ip4.s_addr); + pctx->peer_addr_ip4.s_addr); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to SSGN %pI4\n", - >sgsn_addr_ip4.s_addr); + >peer_addr_ip4.s_addr); dev->stats.tx_carrier_errors++; goto err; } if (rt->dst.dev == dev) { netdev_dbg(dev, "circular route to SSGN %pI4\n", - >sgsn_addr_ip4.s_addr); + >peer_addr_ip4.s_addr); dev->stats.collisions++; goto err_rt; } @@ -894,8 +894,8 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) { pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); pctx->af = AF_INET; - pctx->sgsn_addr_ip4.s_addr = - nla_get_be32(info->attrs[GTPA_SGSN_ADDRESS]); + pctx->peer_addr_ip4.s_addr = + nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); pctx->ms_addr_ip4.s_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); @@ -981,13 +981,13 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) switch (pctx->gtp_version) { case GTP_V0: netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI4 ms=%pI4 (pdp=%p)\n", - pctx->u.v0.tid, >sgsn_addr_ip4, + pctx->u.v0.tid, >peer_addr_ip4, >ms_addr_ip4, pctx); break; case GTP_V1: netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI4 ms=%pI4 (pdp=%p)\n", pctx->u.v1.i_tei, pctx->u.v1.o_tei, - >sgsn_addr_ip4, >ms_addr_ip4, pctx); + >peer_addr_ip4, >ms_addr_ip4, pctx); break; } @@ -1001,7 +1001,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[GTPA_VERSION] || !info->attrs[GTPA_LINK] || - !info->attrs[GTPA_SGSN_ADDRESS] || + !info->attrs[GTPA_PEER_ADDRESS] || !info->attrs[GTPA_MS_ADDRESS]) return -EINVAL; @@ -1114,7 +1114,7 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, goto nlmsg_failure; if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) || - nla_put_be32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr_ip4.s_addr) || + nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr) || nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr)) goto nla_put_failure; @@ -1267,7 +1267,7 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { [GTPA_LINK] = { .type = NLA_U32, }, [GTPA_VERSION] = { .type = NLA_U32, }, [GTPA_TID] = { .type = NLA_U64, }, - [GTPA_SGSN_ADDRESS] = { .type = NLA_U32, }, + [GTPA_PEER_ADDRESS] = { .type = NLA_U32, }, [GTPA_MS_ADDRESS] = { .type = NLA_U32, }, [GTPA_FLOW] = { .type = NLA_U16, }, [GTPA_NET_NS_FD]= { .type = NLA_U32, }, diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index 72a04a0..c51ebb0 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -19,7 +19,7 @@ enum gtp_attrs { GTPA_LINK, GTPA_VERSION, GTPA_TID, /* for GTPv0 only */ -
Re: [PATCH v2 1/2] gtp: rename SGSN netlink attribute
On 03/21/2017 04:07 PM, Pablo Neira Ayuso wrote: On Tue, Mar 21, 2017 at 04:04:29PM +0100, Jonas Bonn wrote: diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index 72a04a0..c51ebb0 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -19,7 +19,7 @@ enum gtp_attrs { GTPA_LINK, GTPA_VERSION, GTPA_TID, /* for GTPv0 only */ - GTPA_SGSN_ADDRESS, + GTPA_PEER_ADDRESS, /* Remote GSN peer, either SGSN or GGSN */ We need here: #define GTPA_SGSN_ADDRESS GTPA_PEER_ADDRESS for backward compatibility. Anything that is exposed through uapi cannot be changed. Yes... look a couple of lines further down... GTPA_MS_ADDRESS, GTPA_FLOW, GTPA_NET_NS_FD, @@ -29,5 +29,6 @@ enum gtp_attrs { __GTPA_MAX, }; #define GTPA_MAX (__GTPA_MAX + 1) +#define GTPA_SGSN_ADDRESS GTPA_PEER_ADDRESS /* maintain legacy attr name */ ... there it is! :) /Jonas #endif /* _UAPI_LINUX_GTP_H_ */ -- 2.9.3
Re: [PATCH 1/1] gtp: support SGSN-side tunnels
Hi Pablo, On 02/06/2017 12:08 PM, Pablo Neira Ayuso wrote: Hi Jonas, On Fri, Feb 03, 2017 at 10:12:31AM +0100, Jonas Bonn wrote: The GTP-tunnel driver is explicitly GGSN-side as it searches for PDP contexts based on the incoming packets _destination_ address. If we want to write an SGSN, then we want to be idenityfing PDP contexts based on _source_ address. This patch adds a "flags" argument at GTP-link creation time to specify whether we are on the GGSN or SGSN side of the tunnel; this flag is then used to determine which part of the IP packet to use in determining the PDP context. So far the implementation that I saw in osmocom relies on userspace code to tunnel data from ME to the SSGN/SGW running on the base station. The data we get from GGSN -> SGSN needs to be places into a SN-PDU (via SNDCP) when sending it to the BTS, right? So I wonder how this can be useful given that we would need to see real IP packets coming to the SSGN that we tunnel into GTP. Fair enough. The use-case I am looking at involves PGW load-testing where the simulated load is generated locally on the SGSN so it _is_ seeing IP packets and the SNDCP is left out altogether. Perhaps this is too pathological to warrant messing with the upstream driver... I don't know: the symmetry does not cost much even if it's of limited use. Couldn't the SNDCP theoretically be a separate node and push IP packets to the SGSN, thus making this useful? Perhaps it's a stretch... /Jonas
[PATCH 1/1] gtp: support SGSN-side tunnels
The GTP-tunnel driver is explicitly GGSN-side as it searches for PDP contexts based on the incoming packets _destination_ address. If we want to write an SGSN, then we want to be idenityfing PDP contexts based on _source_ address. This patch adds a "flags" argument at GTP-link creation time to specify whether we are on the GGSN or SGSN side of the tunnel; this flag is then used to determine which part of the IP packet to use in determining the PDP context. Signed-off-by: Jonas Bonn <jo...@southpole.se> --- drivers/net/gtp.c| 43 --- include/uapi/linux/gtp.h | 2 +- include/uapi/linux/if_link.h | 5 + 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 50349a9..1bbac69 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -72,6 +72,7 @@ struct gtp_dev { struct net *net; struct net_device *dev; + unsigned intflags; unsigned inthash_size; struct hlist_head *tid_hash; struct hlist_head *addr_hash; @@ -150,8 +151,8 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr) return NULL; } -static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, - unsigned int hdrlen) +static bool gtp_check_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, + unsigned int hdrlen, unsigned int flags) { struct iphdr *iph; @@ -160,18 +161,22 @@ static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, iph = (struct iphdr *)(skb->data + hdrlen); - return iph->saddr == pctx->ms_addr_ip4.s_addr; + if (flags & GTP_FLAGS_SGSN) { + return iph->daddr == pctx->ms_addr_ip4.s_addr; + } else { + return iph->saddr == pctx->ms_addr_ip4.s_addr; + } } -/* Check if the inner IP source address in this packet is assigned to any +/* Check if the inner IP address in this packet is assigned to any * existing mobile subscriber. */ -static bool gtp_check_src_ms(struct sk_buff *skb, struct pdp_ctx *pctx, -unsigned int hdrlen) +static bool gtp_check_ms(struct sk_buff *skb, struct pdp_ctx *pctx, +unsigned int hdrlen, unsigned int flags) { switch (ntohs(skb->protocol)) { case ETH_P_IP: - return gtp_check_src_ms_ipv4(skb, pctx, hdrlen); + return gtp_check_ms_ipv4(skb, pctx, hdrlen, flags); } return false; } @@ -205,7 +210,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb, goto out_rcu; } - if (!gtp_check_src_ms(skb, pctx, hdrlen)) { + if (!gtp_check_ms(skb, pctx, hdrlen, gtp->flags)) { netdev_dbg(gtp->dev, "No PDP ctx for this MS\n"); ret = -1; goto out_rcu; @@ -248,7 +253,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb, if (gtp1->flags & GTP1_F_MASK) hdrlen += 4; - /* Make sure the header is larger enough, including extensions. */ + /* Make sure the header is large enough, including extensions. */ if (!pskb_may_pull(skb, hdrlen)) return -1; @@ -262,7 +267,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb, goto out_rcu; } - if (!gtp_check_src_ms(skb, pctx, hdrlen)) { + if (!gtp_check_ms(skb, pctx, hdrlen, gtp->flags)) { netdev_dbg(gtp->dev, "No PDP ctx for this MS\n"); ret = -1; goto out_rcu; @@ -491,7 +496,11 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, * Prepend PDP header with TEI/TID from PDP ctx. */ iph = ip_hdr(skb); - pctx = ipv4_pdp_find(gtp, iph->daddr); + if (gtp->flags & GTP_FLAGS_SGSN) { + pctx = ipv4_pdp_find(gtp, iph->saddr); + } else { + pctx = ipv4_pdp_find(gtp, iph->daddr); + } if (!pctx) { netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n", >daddr); @@ -666,12 +675,23 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, int hashsize, err, fd0, fd1; struct gtp_dev *gtp; struct gtp_net *gn; + unsigned int flags; + + if (data[IFLA_GTP_FLAGS]) { + flags = nla_get_u32(data[IFLA_GTP_FLAGS]); + if (flags & ~GTP_FLAGS_MASK) + return -EINVAL; + } else { + flags = 0; + } if (!data[IFLA_GTP_FD0] || !data[IFLA_GTP_FD1]) return -EINVAL;
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/sk98lin/skge.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 20890e4..eedcbeb 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -5166,7 +5166,7 @@ err_out: #define skge_resume NULL #endif -static struct pci_device_id skge_pci_tbl[] = { +static PCI_DEVICE_TABLE(skge_pci_tbl) = { #ifdef SK98LIN_ALL_DEVICES { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/starfire.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index c49214f..a67bac5 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -337,7 +337,7 @@ enum chipset { CH_6915 = 0, }; -static struct pci_device_id starfire_pci_tbl[] = { +static PCI_DEVICE_TABLE(starfire_pci_tbl) = { { 0x9004, 0x6915, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_6915 }, { 0, } }; -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/skfp/skfddi.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 7cf9b9f..2a8386b 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -150,7 +150,7 @@ extern void mac_drv_rx_mode(struct s_smc *smc, int mode); extern void mac_drv_clear_rx_queue(struct s_smc *smc); extern void enable_tx_irq(struct s_smc *smc, u_short queue); -static struct pci_device_id skfddi_pci_tbl[] = { +static PCI_DEVICE_TABLE(skfddi_pci_tbl) = { { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ }; -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/wan/dscc4.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index c6f26e2..16d3a4c 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -2048,7 +2048,7 @@ static int __init dscc4_setup(char *str) __setup(dscc4.setup=, dscc4_setup); #endif -static struct pci_device_id dscc4_pci_tbl[] = { +static PCI_DEVICE_TABLE(dscc4_pci_tbl) = { { PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_DSCC4, PCI_ANY_ID, PCI_ANY_ID, }, { 0,} -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/niu.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index e98ce1e..ab8148a 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -62,7 +62,7 @@ static void writeq(u64 val, void __iomem *reg) } #endif -static struct pci_device_id niu_pci_tbl[] = { +static PCI_DEVICE_TABLE(niu_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_SUN, 0xabcd)}, {} }; -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/wan/lmc/lmc_main.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 6635ece..e85cfe7 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -82,7 +82,7 @@ static int lmc_first_load = 0; static int LMC_PKT_BUF_SZ = 1542; -static struct pci_device_id lmc_pci_tbl[] = { +static PCI_DEVICE_TABLE(lmc_pci_tbl) = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, PCI_VENDOR_ID_LMC, PCI_ANY_ID }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/hamachi.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index b53f6b6..d8056e9 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1987,7 +1987,7 @@ static void __devexit hamachi_remove_one (struct pci_dev *pdev) } } -static struct pci_device_id hamachi_pci_tbl[] = { +static PCI_DEVICE_TABLE(hamachi_pci_tbl) = { { 0x1318, 0x0911, PCI_ANY_ID, PCI_ANY_ID, }, { 0, } }; -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/amd8111e.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 85f7276..a4ad2fb 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -113,7 +113,7 @@ MODULE_PARM_DESC(coalesce, Enable or Disable interrupt coalescing, 1: Enable, 0 module_param_array(dynamic_ipg, bool, NULL, 0); MODULE_PARM_DESC(dynamic_ipg, Enable or Disable dynamic IPG, 1: Enable, 0: Disable); -static struct pci_device_id amd8111e_pci_tbl[] = { +static PCI_DEVICE_TABLE(amd8111e_pci_tbl) = { { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD8111E_7462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/arcnet/com20020-pci.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index b8c0fa6..87ee0db 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -141,7 +141,7 @@ static void __devexit com20020pci_remove(struct pci_dev *pdev) free_netdev(dev); } -static struct pci_device_id com20020pci_id_table[] = { +static PCI_DEVICE_TABLE(com20020pci_id_table) = { { 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
pci_device_id cleanups
The PCI_DEVICE_TABLE patch I sent earlier doesn't necessarily make much sense by itself... here is a set of patches that apply this macro, in turn moving a lot of this data into __devinitconst which is discardable in certain situations. Hopefully the benefit of this approach is a bit clearer now. drivers/net/3c59x.c |2 +- drivers/net/amd8111e.c|2 +- drivers/net/arcnet/com20020-pci.c |2 +- drivers/net/defxx.c |2 +- drivers/net/hamachi.c |2 +- drivers/net/niu.c |2 +- drivers/net/pasemi_mac.c |2 +- drivers/net/sk98lin/skge.c|2 +- drivers/net/skfp/skfddi.c |2 +- drivers/net/starfire.c|2 +- drivers/net/sunhme.c |2 +- drivers/net/tlan.c|2 +- drivers/net/wan/dscc4.c |2 +- drivers/net/wan/lmc/lmc_main.c|2 +- include/linux/pci.h |9 + 15 files changed, 23 insertions(+), 14 deletions(-) -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/tlan.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 3af5b92..bea59c6 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -253,7 +253,7 @@ static struct board { { Compaq NetFlex-3/E, TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */ }; -static struct pci_device_id tlan_pci_tbl[] = { +static PCI_DEVICE_TABLE(tlan_pci_tbl) = { { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100, -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/defxx.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index ddc30c4..84a3ce5 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -3630,7 +3630,7 @@ static int __devinit dfx_pci_register(struct pci_dev *, const struct pci_device_id *); static void __devexit dfx_pci_unregister(struct pci_dev *); -static struct pci_device_id dfx_pci_table[] = { +static PCI_DEVICE_TABLE(dfx_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) }, { } }; -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/sunhme.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index b4e7f30..beb0d27 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -3247,7 +3247,7 @@ static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) dev_set_drvdata(pdev-dev, NULL); } -static struct pci_device_id happymeal_pci_ids[] = { +static PCI_DEVICE_TABLE(happymeal_pci_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL) }, { } /* Terminating entry */ }; -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/pasemi_mac.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 2e39e02..069fa7c 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -1648,7 +1648,7 @@ static void __devexit pasemi_mac_remove(struct pci_dev *pdev) free_netdev(netdev); } -static struct pci_device_id pasemi_mac_pci_tbl[] = { +static PCI_DEVICE_TABLE(pasemi_mac_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) }, { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) }, { }, -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] Add PCI_DEVICE_TABLE macro
The definitions of struct pci_device_id arrays should generally follow the same pattern across the entire kernel. This macro defines this array as const and puts it into the __devinitconst section. Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- include/linux/pci.h |9 + 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/include/linux/pci.h b/include/linux/pci.h index 87195b6..c7a91b1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -389,6 +389,15 @@ struct pci_driver { #defineto_pci_driver(drv) container_of(drv, struct pci_driver, driver) /** + * PCI_DEVICE_TABLE - macro used to describe a pci device table + * @_table: device table name + * + * This macro is used to create a struct pci_device_id array (a device table) + * in a generic manner. + */ +#define PCI_DEVICE_TABLE(_table) const struct pci_device_id _table[] __devinitconst + +/** * PCI_DEVICE - macro used to describe a specific pci device * @vend: the 16 bit PCI Vendor ID * @dev: the 16 bit PCI Device ID -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [net] use PCI_DEVICE_TABLE: makes struct pci_device_id array const and adds section attribute __devinitconst
Signed-off-by: Jonas Bonn [EMAIL PROTECTED] --- drivers/net/3c59x.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 6f8e7d4..d2045d4 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -372,7 +372,7 @@ static struct vortex_chip_info { }; -static struct pci_device_id vortex_pci_tbl[] = { +static PCI_DEVICE_TABLE(vortex_pci_tbl) = { { 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C590 }, { 0x10B7, 0x5920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C592 }, { 0x10B7, 0x5970, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C597 }, -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: pci_device_id cleanups
Sam Ravnborg wrote: On Wed, Feb 20, 2008 at 01:53:36PM +0100, Jonas Bonn wrote: The PCI_DEVICE_TABLE patch I sent earlier doesn't necessarily make much sense by itself... here is a set of patches that apply this macro, in turn moving a lot of this data into __devinitconst which is discardable in certain situations. Hopefully the benefit of this approach is a bit clearer now. [shorter lines please..] Sorry... Can you please confirm that this does not break powerpc (64 bit) as they have troubles with the constification.. I do not have access to any PowerPC machine... Olof Johansson built the tree I posted earlier on PowerPC; there's nothing really new here except the wrapping of the definition in a macro. But of course, it would great if someone could confirm this... Sam -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: PowerPC toolchain for x86 [Was: pci_device_id cleanups]
Sam Ravnborg wrote: On Wed, Feb 20, 2008 at 02:27:19PM +0100, Jonas Bonn wrote: Sam Ravnborg wrote: On Wed, Feb 20, 2008 at 01:53:36PM +0100, Jonas Bonn wrote: The PCI_DEVICE_TABLE patch I sent earlier doesn't necessarily make much sense by itself... here is a set of patches that apply this macro, in turn moving a lot of this data into __devinitconst which is discardable in certain situations. Hopefully the benefit of this approach is a bit clearer now. [shorter lines please..] Sorry... Can you please confirm that this does not break powerpc (64 bit) as they have troubles with the constification.. I do not have access to any PowerPC machine... Olof Johansson built the tree I posted earlier on PowerPC; there's nothing really new here except the wrapping of the definition in a macro. And you added const and a specific section. No... once the macro is expanded the code is exactly the same as that which built cleanly on powerpc previously (which Olof, built, I mean)... nothing new here. Exactly what could break on PowerPC. To do the build break check is easy. Google for crosstool and build your own powerpc toolchain. Thanks... I'll throw together a cross compiler and see what I can do. /Jonas Andrew has something precompiled somewhere but I lost the link. Sam -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [SIS190] Constify data marked as __devinitdata
This fixes build error as gcc complains about a section type conflict due to the const __devinitdata in sis190_get_mac_addr_from_apc(). --- drivers/net/sis190.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index b570402..e48e4ad 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -326,7 +326,7 @@ static const struct { { SiS 191 PCI Gigabit Ethernet adapter }, }; -static struct pci_device_id sis190_pci_tbl[] __devinitdata = { +static const struct pci_device_id sis190_pci_tbl[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 }, { 0, }, -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [SIS190] Use _devinitconst for const data
This fixes build error as gcc complains about a section type conflict due to the mixing of const and non-const data in same section. --- drivers/net/sis190.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index b570402..f84c02e 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -326,7 +326,7 @@ static const struct { { SiS 191 PCI Gigabit Ethernet adapter }, }; -static struct pci_device_id sis190_pci_tbl[] __devinitdata = { +static struct pci_device_id sis190_pci_tbl[] __devinitconst = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 }, { 0, }, @@ -1556,7 +1556,7 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, struct net_device *dev) { - static const u16 __devinitdata ids[] = { 0x0965, 0x0966, 0x0968 }; + static u16 __devinitconst ids[] = { 0x0965, 0x0966, 0x0968 }; struct sis190_private *tp = netdev_priv(dev); struct pci_dev *isa_bridge; u8 reg, tmp8; -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] [SIS190] Constify data marked as __devinitdata
instead? Because AFAIK, const *and* __sectionmarker does not mix. You're right... it's documented in linux/init.h that const and __sectionmarker do not mix. The compile error is due to the use of const and __section marker in the function sis190_get_mac_addr_from_apc(). -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] [SIS190] Use __devinitconst for const devinit data
Mixing const and __section was previously not allowed. New __devinitconst tag allows this. This fixes a gcc section type mismatch build error. --- drivers/net/sis190.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index b570402..d3126a9 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -326,7 +326,7 @@ static const struct { { SiS 191 PCI Gigabit Ethernet adapter }, }; -static struct pci_device_id sis190_pci_tbl[] __devinitdata = { +static const struct pci_device_id sis190_pci_tbl[] __devinitconst = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 }, { 0, }, @@ -1556,7 +1556,7 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, struct net_device *dev) { - static const u16 __devinitdata ids[] = { 0x0965, 0x0966, 0x0968 }; + static const u16 __devinitconst ids[] = { 0x0965, 0x0966, 0x0968 }; struct sis190_private *tp = netdev_priv(dev); struct pci_dev *isa_bridge; u8 reg, tmp8; -- 1.5.3.8 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html