netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / tests / test-netlink-conntrack.c
1 /*
2  * Copyright (c) 2015 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include <linux/netfilter/nfnetlink.h>
20
21 #include "ct-dpif.h"
22 #include "netlink-conntrack.h"
23 #include "netlink-notifier.h"
24 #include "ovstest.h"
25 #include "poll-loop.h"
26
27 /* Monitor command */
28 struct test_change {
29     enum nl_ct_event_type type;
30     struct ct_dpif_entry entry;
31 };
32
33 static bool
34 event_parse(struct ofpbuf *buf, void *change_)
35 {
36     struct test_change *change = change_;
37
38     return nl_ct_parse_entry(buf, &change->entry, &change->type);
39 }
40
41 static void
42 event_print(const void *change_, void *aux OVS_UNUSED)
43 {
44     const struct test_change *change = change_;
45
46     if (change) {
47         struct ds ds = DS_EMPTY_INITIALIZER;
48
49         nl_ct_format_event_entry(&change->entry, change->type, &ds, true,
50                                  true);
51         printf("%s\n", ds_cstr(&ds));
52         ds_destroy(&ds);
53     }
54 }
55
56 static void
57 test_nl_ct_monitor(struct ovs_cmdl_context *ctx OVS_UNUSED)
58 {
59     int groups [] = {
60         NFNLGRP_CONNTRACK_DESTROY,
61         NFNLGRP_CONNTRACK_NEW,
62         NFNLGRP_CONNTRACK_UPDATE,
63     };
64
65     struct nln *nlns[ARRAY_SIZE(groups)];
66     struct nln_notifier *notifiers[ARRAY_SIZE(groups)];
67
68     struct test_change change;
69
70     unsigned i;
71
72     for (i = 0; i < ARRAY_SIZE(groups); i++) {
73         nlns[i] = nln_create(NETLINK_NETFILTER, groups[i], event_parse,
74                              &change);
75
76         notifiers[i] = nln_notifier_create(nlns[i], event_print, NULL);
77     }
78
79     for (;;) {
80         for (i = 0; i < ARRAY_SIZE(groups); i++) {
81             nln_run(nlns[i]);
82             nln_wait(nlns[i]);
83         }
84         poll_block();
85     }
86
87     for (i = 0; i < ARRAY_SIZE(groups); i++) {
88         nln_notifier_destroy(notifiers[i]);
89         nln_destroy(nlns[i]);
90     }
91 }
92 \f
93 /* Dump command */
94 static void
95 test_nl_ct_dump(struct ovs_cmdl_context *ctx)
96 {
97     struct nl_ct_dump_state *dump;
98     uint16_t zone, *pzone = NULL;
99     struct ct_dpif_entry entry;
100     int err;
101
102     if (ctx->argc >= 2) {
103         if (!ovs_scan(ctx->argv[1], "zone=%"SCNu16, &zone)) {
104             ovs_fatal(0, "Error parsing zone= specifier");
105         }
106         pzone = &zone;
107     }
108     err = nl_ct_dump_start(&dump, pzone);
109     if (err) {
110         ovs_fatal(err, "Error creating conntrack netlink dump");
111     }
112
113     do {
114         err = nl_ct_dump_next(dump, &entry);
115         if (!err) {
116             struct ds ds = DS_EMPTY_INITIALIZER;
117
118             ct_dpif_format_entry(&entry, &ds, true, true);
119             printf("%s\n", ds_cstr(&ds));
120             ds_destroy(&ds);
121         }
122     } while (!err);
123
124     if (err != EOF) {
125         ovs_fatal(err, "Error dumping conntrack netlink entry");
126     }
127     nl_ct_dump_done(dump);
128 }
129 \f
130 /* Flush command */
131 static void
132 test_nl_ct_flush(struct ovs_cmdl_context *ctx OVS_UNUSED)
133 {
134     int err;
135
136     if (ctx->argc >= 2) {
137         uint16_t zone;
138
139         if (ovs_scan(ctx->argv[1], "zone=%"SCNu16, &zone)) {
140             err = nl_ct_flush_zone(zone);
141         } else {
142             ovs_fatal(0, "Error parsing zone= specifier");
143         }
144     } else {
145         err = nl_ct_flush();
146     }
147     if (err) {
148         ovs_fatal(err, "Error flushing conntrack netlink");
149     }
150 }
151 \f
152 static const struct ovs_cmdl_command commands[] = {
153     /* Linux netlink connection tracker interface test. */
154
155     /* Prints all the entries in the connection table and exits. */
156     {"dump", "[zone=zone]", 0, 1, test_nl_ct_dump},
157     /* Listens to all the connection tracking events and prints them to
158      * standard output until killed. */
159     {"monitor", "", 0, 0, test_nl_ct_monitor},
160     /* Flushes all the entries from all the tables.. */
161     {"flush", "[zone=zone]", 0, 1, test_nl_ct_flush},
162
163     {NULL, NULL, 0, 0, NULL},
164 };
165
166 static void
167 test_netlink_conntrack(int argc, char *argv[])
168 {
169     struct ovs_cmdl_context ctx = {
170         .argc = argc - 1,
171         .argv = argv + 1,
172     };
173     set_program_name(argv[0]);
174     ovs_cmdl_run_command(&ctx, commands);
175 }
176
177 OVSTEST_REGISTER("test-netlink-conntrack", test_netlink_conntrack);