Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  cgroup_tcp_skb.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Facebook */
#include <test_progs.h>
#include <linux/in6.h>
#include <sys/socket.h>
#include <sched.h>
#include <unistd.h>
#include "cgroup_helpers.h"
#include "testing_helpers.h"
#include "cgroup_tcp_skb.skel.h"
#include "cgroup_tcp_skb.h"
#include "network_helpers.h"

#define CGROUP_TCP_SKB_PATH "/test_cgroup_tcp_skb"

static int install_filters(int cgroup_fd,
      struct bpf_link **egress_link,
      struct bpf_link **ingress_link,
      struct bpf_program *egress_prog,
      struct bpf_program *ingress_prog,
      struct cgroup_tcp_skb *skel)
{
 /* Prepare filters */
 skel->bss->g_sock_state = 0;
 skel->bss->g_unexpected = 0;
 *egress_link =
  bpf_program__attach_cgroup(egress_prog,
        cgroup_fd);
 if (!ASSERT_OK_PTR(egress_link, "egress_link"))
  return -1;
 *ingress_link =
  bpf_program__attach_cgroup(ingress_prog,
        cgroup_fd);
 if (!ASSERT_OK_PTR(ingress_link, "ingress_link"))
  return -1;

 return 0;
}

static void uninstall_filters(struct bpf_link **egress_link,
         struct bpf_link **ingress_link)
{
 bpf_link__destroy(*egress_link);
 *egress_link = NULL;
 bpf_link__destroy(*ingress_link);
 *ingress_link = NULL;
}

static int create_client_sock_v6(void)
{
 int fd;

 fd = socket(AF_INET6, SOCK_STREAM, 0);
 if (fd < 0) {
  perror("socket");
  return -1;
 }

 return fd;
}

/* Connect to the server in a cgroup from the outside of the cgroup. */
static int talk_to_cgroup(int *client_fd, int *listen_fd, int *service_fd,
     struct cgroup_tcp_skb *skel)
{
 int err, cp;
 char buf[5];
 int port;

 /* Create client & server socket */
 err = join_root_cgroup();
 if (!ASSERT_OK(err, "join_root_cgroup"))
  return -1;
 *client_fd = create_client_sock_v6();
 if (!ASSERT_GE(*client_fd, 0, "client_fd"))
  return -1;
 err = join_cgroup(CGROUP_TCP_SKB_PATH);
 if (!ASSERT_OK(err, "join_cgroup"))
  return -1;
 *listen_fd = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
 if (!ASSERT_GE(*listen_fd, 0, "listen_fd"))
  return -1;
 port = get_socket_local_port(*listen_fd);
 if (!ASSERT_GE(port, 0, "get_socket_local_port"))
  return -1;
 skel->bss->g_sock_port = ntohs(port);

 /* Connect client to server */
 err = connect_fd_to_fd(*client_fd, *listen_fd, 0);
 if (!ASSERT_OK(err, "connect_fd_to_fd"))
  return -1;
 *service_fd = accept(*listen_fd, NULL, NULL);
 if (!ASSERT_GE(*service_fd, 0, "service_fd"))
  return -1;
 err = join_root_cgroup();
 if (!ASSERT_OK(err, "join_root_cgroup"))
  return -1;
 cp = write(*client_fd, "hello", 5);
 if (!ASSERT_EQ(cp, 5, "write"))
  return -1;
 cp = read(*service_fd, buf, 5);
 if (!ASSERT_EQ(cp, 5, "read"))
  return -1;

 return 0;
}

/* Connect to the server out of a cgroup from inside the cgroup. */
static int talk_to_outside(int *client_fd, int *listen_fd, int *service_fd,
      struct cgroup_tcp_skb *skel)

{
 int err, cp;
 char buf[5];
 int port;

 /* Create client & server socket */
 err = join_root_cgroup();
 if (!ASSERT_OK(err, "join_root_cgroup"))
  return -1;
 *listen_fd = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
 if (!ASSERT_GE(*listen_fd, 0, "listen_fd"))
  return -1;
 err = join_cgroup(CGROUP_TCP_SKB_PATH);
 if (!ASSERT_OK(err, "join_cgroup"))
  return -1;
 *client_fd = create_client_sock_v6();
 if (!ASSERT_GE(*client_fd, 0, "client_fd"))
  return -1;
 err = join_root_cgroup();
 if (!ASSERT_OK(err, "join_root_cgroup"))
  return -1;
 port = get_socket_local_port(*listen_fd);
 if (!ASSERT_GE(port, 0, "get_socket_local_port"))
  return -1;
 skel->bss->g_sock_port = ntohs(port);

 /* Connect client to server */
 err = connect_fd_to_fd(*client_fd, *listen_fd, 0);
 if (!ASSERT_OK(err, "connect_fd_to_fd"))
  return -1;
 *service_fd = accept(*listen_fd, NULL, NULL);
 if (!ASSERT_GE(*service_fd, 0, "service_fd"))
  return -1;
 cp = write(*client_fd, "hello", 5);
 if (!ASSERT_EQ(cp, 5, "write"))
  return -1;
 cp = read(*service_fd, buf, 5);
 if (!ASSERT_EQ(cp, 5, "read"))
  return -1;

 return 0;
}

static int close_connection(int *closing_fd, int *peer_fd, int *listen_fd,
       struct cgroup_tcp_skb *skel)
{
 __u32 saved_packet_count = 0;
 int err;
 int i;

 /* Wait for ACKs to be sent */
 saved_packet_count = skel->bss->g_packet_count;
 usleep(100000);  /* 0.1s */
 for (i = 0;
      skel->bss->g_packet_count != saved_packet_count && i < 10;
      i++) {
  saved_packet_count = skel->bss->g_packet_count;
  usleep(100000); /* 0.1s */
 }
 if (!ASSERT_EQ(skel->bss->g_packet_count, saved_packet_count,
         "packet_count"))
  return -1;

 skel->bss->g_packet_count = 0;
 saved_packet_count = 0;

 /* Half shutdown to make sure the closing socket having a chance to
 * receive a FIN from the peer.
 */

 err = shutdown(*closing_fd, SHUT_WR);
 if (!ASSERT_OK(err, "shutdown closing_fd"))
  return -1;

 /* Wait for FIN and the ACK of the FIN to be observed */
 for (i = 0;
      skel->bss->g_packet_count < saved_packet_count + 2 && i < 10;
      i++)
  usleep(100000); /* 0.1s */
 if (!ASSERT_GE(skel->bss->g_packet_count, saved_packet_count + 2,
         "packet_count"))
  return -1;

 saved_packet_count = skel->bss->g_packet_count;

 /* Fully shutdown the connection */
 err = close(*peer_fd);
 if (!ASSERT_OK(err, "close peer_fd"))
  return -1;
 *peer_fd = -1;

 /* Wait for FIN and the ACK of the FIN to be observed */
 for (i = 0;
      skel->bss->g_packet_count < saved_packet_count + 2 && i < 10;
      i++)
  usleep(100000); /* 0.1s */
 if (!ASSERT_GE(skel->bss->g_packet_count, saved_packet_count + 2,
         "packet_count"))
  return -1;

 err = close(*closing_fd);
 if (!ASSERT_OK(err, "close closing_fd"))
  return -1;
 *closing_fd = -1;

 close(*listen_fd);
 *listen_fd = -1;

 return 0;
}

/* This test case includes four scenarios:
 * 1. Connect to the server from outside the cgroup and close the connection
 *    from outside the cgroup.
 * 2. Connect to the server from outside the cgroup and close the connection
 *    from inside the cgroup.
 * 3. Connect to the server from inside the cgroup and close the connection
 *    from outside the cgroup.
 * 4. Connect to the server from inside the cgroup and close the connection
 *    from inside the cgroup.
 *
 * The test case is to verify that cgroup_skb/{egress,ingress} filters
 * receive expected packets including SYN, SYN/ACK, ACK, FIN, and FIN/ACK.
 */

void test_cgroup_tcp_skb(void)
{
 struct bpf_link *ingress_link = NULL;
 struct bpf_link *egress_link = NULL;
 int client_fd = -1, listen_fd = -1;
 struct cgroup_tcp_skb *skel;
 int service_fd = -1;
 int cgroup_fd = -1;
 int err;

 skel = cgroup_tcp_skb__open_and_load();
 if (!ASSERT_OK(!skel, "skel_open_load"))
  return;

 err = setup_cgroup_environment();
 if (!ASSERT_OK(err, "setup_cgroup_environment"))
  goto cleanup;

 cgroup_fd = create_and_get_cgroup(CGROUP_TCP_SKB_PATH);
 if (!ASSERT_GE(cgroup_fd, 0, "cgroup_fd"))
  goto cleanup;

 /* Scenario 1 */
 err = install_filters(cgroup_fd, &egress_link, &ingress_link,
         skel->progs.server_egress,
         skel->progs.server_ingress,
         skel);
 if (!ASSERT_OK(err, "install_filters"))
  goto cleanup;

 err = talk_to_cgroup(&client_fd, &listen_fd, &service_fd, skel);
 if (!ASSERT_OK(err, "talk_to_cgroup"))
  goto cleanup;

 err = close_connection(&client_fd, &service_fd, &listen_fd, skel);
 if (!ASSERT_OK(err, "close_connection"))
  goto cleanup;

 ASSERT_EQ(skel->bss->g_unexpected, 0, "g_unexpected");
 ASSERT_EQ(skel->bss->g_sock_state, CLOSED, "g_sock_state");

 uninstall_filters(&egress_link, &ingress_link);

 /* Scenario 2 */
 err = install_filters(cgroup_fd, &egress_link, &ingress_link,
         skel->progs.server_egress_srv,
         skel->progs.server_ingress_srv,
         skel);

 err = talk_to_cgroup(&client_fd, &listen_fd, &service_fd, skel);
 if (!ASSERT_OK(err, "talk_to_cgroup"))
  goto cleanup;

 err = close_connection(&service_fd, &client_fd, &listen_fd, skel);
 if (!ASSERT_OK(err, "close_connection"))
  goto cleanup;

 ASSERT_EQ(skel->bss->g_unexpected, 0, "g_unexpected");
 ASSERT_EQ(skel->bss->g_sock_state, TIME_WAIT, "g_sock_state");

 uninstall_filters(&egress_link, &ingress_link);

 /* Scenario 3 */
 err = install_filters(cgroup_fd, &egress_link, &ingress_link,
         skel->progs.client_egress_srv,
         skel->progs.client_ingress_srv,
         skel);

 err = talk_to_outside(&client_fd, &listen_fd, &service_fd, skel);
 if (!ASSERT_OK(err, "talk_to_outside"))
  goto cleanup;

 err = close_connection(&service_fd, &client_fd, &listen_fd, skel);
 if (!ASSERT_OK(err, "close_connection"))
  goto cleanup;

 ASSERT_EQ(skel->bss->g_unexpected, 0, "g_unexpected");
 ASSERT_EQ(skel->bss->g_sock_state, CLOSED, "g_sock_state");

 uninstall_filters(&egress_link, &ingress_link);

 /* Scenario 4 */
 err = install_filters(cgroup_fd, &egress_link, &ingress_link,
         skel->progs.client_egress,
         skel->progs.client_ingress,
         skel);

 err = talk_to_outside(&client_fd, &listen_fd, &service_fd, skel);
 if (!ASSERT_OK(err, "talk_to_outside"))
  goto cleanup;

 err = close_connection(&client_fd, &service_fd, &listen_fd, skel);
 if (!ASSERT_OK(err, "close_connection"))
  goto cleanup;

 ASSERT_EQ(skel->bss->g_unexpected, 0, "g_unexpected");
 ASSERT_EQ(skel->bss->g_sock_state, TIME_WAIT, "g_sock_state");

 uninstall_filters(&egress_link, &ingress_link);

cleanup:
 close(client_fd);
 close(listen_fd);
 close(service_fd);
 close(cgroup_fd);
 bpf_link__destroy(egress_link);
 bpf_link__destroy(ingress_link);
 cleanup_cgroup_environment();
 cgroup_tcp_skb__destroy(skel);
}

Messung V0.5
C=97 H=90 G=93

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge