Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gtp: Implement GTP echo request

Adding GTP device through ip link creates the situation where
GTP instance is not able to send GTP echo requests.
Echo requests are used to check if GTP peer is still alive.
With this patch, gtp_genl_ops are extended by new cmd (GTP_CMD_ECHOREQ)
which allows to send echo request in the given version of GTP
protocol (v0 or v1), from the given ms address to he given
peer. TID is not inclued because in all path management
messages it should be equal to 0.

When GTP echo response is detected, multicast message is
send to everyone in the gtp_genl_family. Message contains
GTP version, ms address and peer address.

Suggested-by: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com>
Reviewed-by: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>

authored by

Wojciech Drewek and committed by
Tony Nguyen
d33bd757 9af41cc3

+269 -37
+268 -37
drivers/net/gtp.c
··· 79 79 u8 restart_count; 80 80 }; 81 81 82 + struct echo_info { 83 + struct in_addr ms_addr_ip4; 84 + struct in_addr peer_addr_ip4; 85 + u8 gtp_version; 86 + }; 87 + 82 88 static unsigned int gtp_net_id __read_mostly; 83 89 84 90 struct gtp_net { ··· 92 86 }; 93 87 94 88 static u32 gtp_h_initval; 89 + 90 + static struct genl_family gtp_genl_family; 91 + 92 + enum gtp_multicast_groups { 93 + GTP_GENL_MCGRP, 94 + }; 95 + 96 + static const struct genl_multicast_group gtp_genl_mcgrps[] = { 97 + [GTP_GENL_MCGRP] = { .name = GTP_GENL_MCGRP_NAME }, 98 + }; 95 99 96 100 static void pdp_context_delete(struct pdp_ctx *pctx); 97 101 ··· 259 243 * by the receiver 260 244 * Returns true if the echo req was correct, false otherwise. 261 245 */ 262 - static bool gtp0_validate_echo_req(struct gtp0_header *gtp0) 246 + static bool gtp0_validate_echo_hdr(struct gtp0_header *gtp0) 263 247 { 264 248 return !(gtp0->tid || (gtp0->flags ^ 0x1e) || 265 249 gtp0->number != 0xff || gtp0->flow); 250 + } 251 + 252 + /* msg_type has to be GTP_ECHO_REQ or GTP_ECHO_RSP */ 253 + static void gtp0_build_echo_msg(struct gtp0_header *hdr, __u8 msg_type) 254 + { 255 + int len_pkt, len_hdr; 256 + 257 + hdr->flags = 0x1e; /* v0, GTP-non-prime. */ 258 + hdr->type = msg_type; 259 + /* GSM TS 09.60. 7.3 In all Path Management Flow Label and TID 260 + * are not used and shall be set to 0. 261 + */ 262 + hdr->flow = 0; 263 + hdr->tid = 0; 264 + hdr->number = 0xff; 265 + hdr->spare[0] = 0xff; 266 + hdr->spare[1] = 0xff; 267 + hdr->spare[2] = 0xff; 268 + 269 + len_pkt = sizeof(struct gtp0_packet); 270 + len_hdr = sizeof(struct gtp0_header); 271 + 272 + if (msg_type == GTP_ECHO_RSP) 273 + hdr->length = htons(len_pkt - len_hdr); 274 + else 275 + hdr->length = 0; 266 276 } 267 277 268 278 static int gtp0_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) ··· 302 260 303 261 gtp0 = (struct gtp0_header *)(skb->data + sizeof(struct udphdr)); 304 262 305 - if (!gtp0_validate_echo_req(gtp0)) 263 + if (!gtp0_validate_echo_hdr(gtp0)) 306 264 return -1; 307 265 308 266 seq = gtp0->seq; ··· 313 271 gtp_pkt = skb_push(skb, sizeof(struct gtp0_packet)); 314 272 memset(gtp_pkt, 0, sizeof(struct gtp0_packet)); 315 273 316 - gtp_pkt->gtp0_h.flags = 0x1e; /* v0, GTP-non-prime. */ 317 - gtp_pkt->gtp0_h.type = GTP_ECHO_RSP; 318 - gtp_pkt->gtp0_h.length = 319 - htons(sizeof(struct gtp0_packet) - sizeof(struct gtp0_header)); 274 + gtp0_build_echo_msg(&gtp_pkt->gtp0_h, GTP_ECHO_RSP); 320 275 321 276 /* GSM TS 09.60. 7.3 The Sequence Number in a signalling response 322 277 * message shall be copied from the signalling request message 323 278 * that the GSN is replying to. 324 279 */ 325 280 gtp_pkt->gtp0_h.seq = seq; 326 - 327 - /* GSM TS 09.60. 7.3 In all Path Management Flow Label and TID 328 - * are not used and shall be set to 0. 329 - */ 330 - gtp_pkt->gtp0_h.flow = 0; 331 - gtp_pkt->gtp0_h.tid = 0; 332 - gtp_pkt->gtp0_h.number = 0xff; 333 - gtp_pkt->gtp0_h.spare[0] = 0xff; 334 - gtp_pkt->gtp0_h.spare[1] = 0xff; 335 - gtp_pkt->gtp0_h.spare[2] = 0xff; 336 281 337 282 gtp_pkt->ie.tag = GTPIE_RECOVERY; 338 283 gtp_pkt->ie.val = gtp->restart_count; ··· 348 319 return 0; 349 320 } 350 321 322 + static int gtp_genl_fill_echo(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, 323 + int flags, u32 type, struct echo_info echo) 324 + { 325 + void *genlh; 326 + 327 + genlh = genlmsg_put(skb, snd_portid, snd_seq, &gtp_genl_family, flags, 328 + type); 329 + if (!genlh) 330 + goto failure; 331 + 332 + if (nla_put_u32(skb, GTPA_VERSION, echo.gtp_version) || 333 + nla_put_be32(skb, GTPA_PEER_ADDRESS, echo.peer_addr_ip4.s_addr) || 334 + nla_put_be32(skb, GTPA_MS_ADDRESS, echo.ms_addr_ip4.s_addr)) 335 + goto failure; 336 + 337 + genlmsg_end(skb, genlh); 338 + return 0; 339 + 340 + failure: 341 + genlmsg_cancel(skb, genlh); 342 + return -EMSGSIZE; 343 + } 344 + 345 + static int gtp0_handle_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) 346 + { 347 + struct gtp0_header *gtp0; 348 + struct echo_info echo; 349 + struct sk_buff *msg; 350 + struct iphdr *iph; 351 + int ret; 352 + 353 + gtp0 = (struct gtp0_header *)(skb->data + sizeof(struct udphdr)); 354 + 355 + if (!gtp0_validate_echo_hdr(gtp0)) 356 + return -1; 357 + 358 + iph = ip_hdr(skb); 359 + echo.ms_addr_ip4.s_addr = iph->daddr; 360 + echo.peer_addr_ip4.s_addr = iph->saddr; 361 + echo.gtp_version = GTP_V0; 362 + 363 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 364 + if (!msg) 365 + return -ENOMEM; 366 + 367 + ret = gtp_genl_fill_echo(msg, 0, 0, 0, GTP_CMD_ECHOREQ, echo); 368 + if (ret < 0) { 369 + nlmsg_free(msg); 370 + return ret; 371 + } 372 + 373 + return genlmsg_multicast_netns(&gtp_genl_family, dev_net(gtp->dev), 374 + msg, 0, GTP_GENL_MCGRP, GFP_ATOMIC); 375 + } 376 + 351 377 /* 1 means pass up to the stack, -1 means drop and 0 means decapsulated. */ 352 378 static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) 353 379 { ··· 426 342 if (gtp0->type == GTP_ECHO_REQ && gtp->sk_created) 427 343 return gtp0_send_echo_resp(gtp, skb); 428 344 345 + if (gtp0->type == GTP_ECHO_RSP && gtp->sk_created) 346 + return gtp0_handle_echo_resp(gtp, skb); 347 + 429 348 if (gtp0->type != GTP_TPDU) 430 349 return 1; 431 350 ··· 439 352 } 440 353 441 354 return gtp_rx(pctx, skb, hdrlen, gtp->role); 355 + } 356 + 357 + /* msg_type has to be GTP_ECHO_REQ or GTP_ECHO_RSP */ 358 + static void gtp1u_build_echo_msg(struct gtp1_header_long *hdr, __u8 msg_type) 359 + { 360 + int len_pkt, len_hdr; 361 + 362 + /* S flag must be set to 1 */ 363 + hdr->flags = 0x32; /* v1, GTP-non-prime. */ 364 + hdr->type = msg_type; 365 + /* 3GPP TS 29.281 5.1 - TEID has to be set to 0 */ 366 + hdr->tid = 0; 367 + 368 + /* seq, npdu and next should be counted to the length of the GTP packet 369 + * that's why szie of gtp1_header should be subtracted, 370 + * not size of gtp1_header_long. 371 + */ 372 + 373 + len_hdr = sizeof(struct gtp1_header); 374 + 375 + if (msg_type == GTP_ECHO_RSP) { 376 + len_pkt = sizeof(struct gtp1u_packet); 377 + hdr->length = htons(len_pkt - len_hdr); 378 + } else { 379 + /* GTP_ECHO_REQ does not carry GTP Information Element, 380 + * the why gtp1_header_long is used here. 381 + */ 382 + len_pkt = sizeof(struct gtp1_header_long); 383 + hdr->length = htons(len_pkt - len_hdr); 384 + } 442 385 } 443 386 444 387 static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) ··· 495 378 gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet)); 496 379 memset(gtp_pkt, 0, sizeof(struct gtp1u_packet)); 497 380 498 - /* S flag must be set to 1 */ 499 - gtp_pkt->gtp1u_h.flags = 0x32; 500 - gtp_pkt->gtp1u_h.type = GTP_ECHO_RSP; 501 - /* seq, npdu and next should be counted to the length of the GTP packet 502 - * that's why szie of gtp1_header should be subtracted, 503 - * not why szie of gtp1_header_long. 504 - */ 505 - gtp_pkt->gtp1u_h.length = 506 - htons(sizeof(struct gtp1u_packet) - sizeof(struct gtp1_header)); 507 - /* 3GPP TS 29.281 5.1 - TEID has to be set to 0 */ 508 - gtp_pkt->gtp1u_h.tid = 0; 381 + gtp1u_build_echo_msg(&gtp_pkt->gtp1u_h, GTP_ECHO_RSP); 509 382 510 383 /* 3GPP TS 29.281 7.7.2 - The Restart Counter value in the 511 384 * Recovery information element shall not be used, i.e. it shall ··· 530 423 return 0; 531 424 } 532 425 426 + static int gtp1u_handle_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) 427 + { 428 + struct gtp1_header_long *gtp1u; 429 + struct echo_info echo; 430 + struct sk_buff *msg; 431 + struct iphdr *iph; 432 + int ret; 433 + 434 + gtp1u = (struct gtp1_header_long *)(skb->data + sizeof(struct udphdr)); 435 + 436 + /* 3GPP TS 29.281 5.1 - For the Echo Request, Echo Response, 437 + * Error Indication and Supported Extension Headers Notification 438 + * messages, the S flag shall be set to 1 and TEID shall be set to 0. 439 + */ 440 + if (!(gtp1u->flags & GTP1_F_SEQ) || gtp1u->tid) 441 + return -1; 442 + 443 + iph = ip_hdr(skb); 444 + echo.ms_addr_ip4.s_addr = iph->daddr; 445 + echo.peer_addr_ip4.s_addr = iph->saddr; 446 + echo.gtp_version = GTP_V1; 447 + 448 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 449 + if (!msg) 450 + return -ENOMEM; 451 + 452 + ret = gtp_genl_fill_echo(msg, 0, 0, 0, GTP_CMD_ECHOREQ, echo); 453 + if (ret < 0) { 454 + nlmsg_free(msg); 455 + return ret; 456 + } 457 + 458 + return genlmsg_multicast_netns(&gtp_genl_family, dev_net(gtp->dev), 459 + msg, 0, GTP_GENL_MCGRP, GFP_ATOMIC); 460 + } 461 + 533 462 static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) 534 463 { 535 464 unsigned int hdrlen = sizeof(struct udphdr) + ··· 587 444 */ 588 445 if (gtp1->type == GTP_ECHO_REQ && gtp->sk_created) 589 446 return gtp1u_send_echo_resp(gtp, skb); 447 + 448 + if (gtp1->type == GTP_ECHO_RSP && gtp->sk_created) 449 + return gtp1u_handle_echo_resp(gtp, skb); 590 450 591 451 if (gtp1->type != GTP_TPDU) 592 452 return 1; ··· 1577 1431 return err; 1578 1432 } 1579 1433 1580 - static struct genl_family gtp_genl_family; 1581 - 1582 - enum gtp_multicast_groups { 1583 - GTP_GENL_MCGRP, 1584 - }; 1585 - 1586 - static const struct genl_multicast_group gtp_genl_mcgrps[] = { 1587 - [GTP_GENL_MCGRP] = { .name = GTP_GENL_MCGRP_NAME }, 1588 - }; 1589 - 1590 1434 static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, 1591 1435 int flags, u32 type, struct pdp_ctx *pctx) 1592 1436 { ··· 1720 1584 return skb->len; 1721 1585 } 1722 1586 1587 + static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) 1588 + { 1589 + struct sk_buff *skb_to_send; 1590 + __be32 src_ip, dst_ip; 1591 + unsigned int version; 1592 + struct gtp_dev *gtp; 1593 + struct flowi4 fl4; 1594 + struct rtable *rt; 1595 + struct sock *sk; 1596 + __be16 port; 1597 + int len; 1598 + 1599 + if (!info->attrs[GTPA_VERSION] || 1600 + !info->attrs[GTPA_LINK] || 1601 + !info->attrs[GTPA_PEER_ADDRESS] || 1602 + !info->attrs[GTPA_MS_ADDRESS]) 1603 + return -EINVAL; 1604 + 1605 + version = nla_get_u32(info->attrs[GTPA_VERSION]); 1606 + dst_ip = nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); 1607 + src_ip = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); 1608 + 1609 + gtp = gtp_find_dev(sock_net(skb->sk), info->attrs); 1610 + if (!gtp) 1611 + return -ENODEV; 1612 + 1613 + if (!gtp->sk_created) 1614 + return -EOPNOTSUPP; 1615 + if (!(gtp->dev->flags & IFF_UP)) 1616 + return -ENETDOWN; 1617 + 1618 + if (version == GTP_V0) { 1619 + struct gtp0_header *gtp0_h; 1620 + 1621 + len = LL_RESERVED_SPACE(gtp->dev) + sizeof(struct gtp0_header) + 1622 + sizeof(struct iphdr) + sizeof(struct udphdr); 1623 + 1624 + skb_to_send = netdev_alloc_skb_ip_align(gtp->dev, len); 1625 + if (!skb_to_send) 1626 + return -ENOMEM; 1627 + 1628 + sk = gtp->sk0; 1629 + port = htons(GTP0_PORT); 1630 + 1631 + gtp0_h = skb_push(skb_to_send, sizeof(struct gtp0_header)); 1632 + memset(gtp0_h, 0, sizeof(struct gtp0_header)); 1633 + gtp0_build_echo_msg(gtp0_h, GTP_ECHO_REQ); 1634 + } else if (version == GTP_V1) { 1635 + struct gtp1_header_long *gtp1u_h; 1636 + 1637 + len = LL_RESERVED_SPACE(gtp->dev) + 1638 + sizeof(struct gtp1_header_long) + 1639 + sizeof(struct iphdr) + sizeof(struct udphdr); 1640 + 1641 + skb_to_send = netdev_alloc_skb_ip_align(gtp->dev, len); 1642 + if (!skb_to_send) 1643 + return -ENOMEM; 1644 + 1645 + sk = gtp->sk1u; 1646 + port = htons(GTP1U_PORT); 1647 + 1648 + gtp1u_h = skb_push(skb_to_send, 1649 + sizeof(struct gtp1_header_long)); 1650 + memset(gtp1u_h, 0, sizeof(struct gtp1_header_long)); 1651 + gtp1u_build_echo_msg(gtp1u_h, GTP_ECHO_REQ); 1652 + } else { 1653 + return -ENODEV; 1654 + } 1655 + 1656 + rt = ip4_route_output_gtp(&fl4, sk, dst_ip, src_ip); 1657 + if (IS_ERR(rt)) { 1658 + netdev_dbg(gtp->dev, "no route for echo request to %pI4\n", 1659 + &dst_ip); 1660 + kfree_skb(skb_to_send); 1661 + return -ENODEV; 1662 + } 1663 + 1664 + udp_tunnel_xmit_skb(rt, sk, skb_to_send, 1665 + fl4.saddr, fl4.daddr, 1666 + fl4.flowi4_tos, 1667 + ip4_dst_hoplimit(&rt->dst), 1668 + 0, 1669 + port, port, 1670 + !net_eq(sock_net(sk), 1671 + dev_net(gtp->dev)), 1672 + false); 1673 + return 0; 1674 + } 1675 + 1723 1676 static const struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { 1724 1677 [GTPA_LINK] = { .type = NLA_U32, }, 1725 1678 [GTPA_VERSION] = { .type = NLA_U32, }, ··· 1839 1614 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1840 1615 .doit = gtp_genl_get_pdp, 1841 1616 .dumpit = gtp_genl_dump_pdp, 1617 + .flags = GENL_ADMIN_PERM, 1618 + }, 1619 + { 1620 + .cmd = GTP_CMD_ECHOREQ, 1621 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1622 + .doit = gtp_genl_send_echo_req, 1842 1623 .flags = GENL_ADMIN_PERM, 1843 1624 }, 1844 1625 };
+1
include/uapi/linux/gtp.h
··· 8 8 GTP_CMD_NEWPDP, 9 9 GTP_CMD_DELPDP, 10 10 GTP_CMD_GETPDP, 11 + GTP_CMD_ECHOREQ, 11 12 12 13 GTP_CMD_MAX, 13 14 };