Branch data Line data Source code
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 <stdlib.h>
20 : : #include <linux/netfilter/nfnetlink.h>
21 : :
22 : : #include "ct-dpif.h"
23 : : #include "netlink-conntrack.h"
24 : : #include "netlink-notifier.h"
25 : : #include "ovstest.h"
26 : : #include "poll-loop.h"
27 : :
28 : : /* Monitor command */
29 : : struct test_change {
30 : : enum nl_ct_event_type type;
31 : : struct ct_dpif_entry entry;
32 : : };
33 : :
34 : : static int
35 : 0 : event_parse(struct ofpbuf *buf, void *change_)
36 : : {
37 : 0 : struct test_change *change = change_;
38 : :
39 [ # # ]: 0 : if (nl_ct_parse_entry(buf, &change->entry, &change->type)) {
40 [ # # # # ]: 0 : switch (change->type) {
41 : : case NL_CT_EVENT_NEW:
42 : 0 : return NFNLGRP_CONNTRACK_NEW;
43 : : case NL_CT_EVENT_UPDATE:
44 : 0 : return NFNLGRP_CONNTRACK_UPDATE;
45 : : case NL_CT_EVENT_DELETE:
46 : 0 : return NFNLGRP_CONNTRACK_DESTROY;
47 : : }
48 : : }
49 : 0 : return 0;
50 : : }
51 : :
52 : : static void
53 : 0 : event_print(const void *change_, void *aux OVS_UNUSED)
54 : : {
55 : 0 : const struct test_change *change = change_;
56 : :
57 [ # # ]: 0 : if (change) {
58 : 0 : struct ds ds = DS_EMPTY_INITIALIZER;
59 : :
60 : 0 : nl_ct_format_event_entry(&change->entry, change->type, &ds, true,
61 : : true);
62 : 0 : printf("%s\n", ds_cstr(&ds));
63 : 0 : ds_destroy(&ds);
64 : : }
65 : 0 : }
66 : :
67 : : static void
68 : 0 : test_nl_ct_monitor(struct ovs_cmdl_context *ctx OVS_UNUSED)
69 : : {
70 : 0 : int groups [] = {
71 : : NFNLGRP_CONNTRACK_DESTROY,
72 : : NFNLGRP_CONNTRACK_NEW,
73 : : NFNLGRP_CONNTRACK_UPDATE,
74 : : };
75 : :
76 : : struct nln *nln;
77 : : struct nln_notifier *notifiers[ARRAY_SIZE(groups)];
78 : :
79 : : struct test_change change;
80 : :
81 : : unsigned i;
82 : :
83 : 0 : nln = nln_create(NETLINK_NETFILTER, event_parse, &change);
84 : :
85 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(groups); i++) {
86 : 0 : notifiers[i] = nln_notifier_create(nln, groups[i], event_print, NULL);
87 : : }
88 : :
89 : : for (;;) {
90 : 0 : nln_run(nln);
91 : 0 : nln_wait(nln);
92 : 0 : poll_block();
93 : 0 : }
94 : :
95 : : for (i = 0; i < ARRAY_SIZE(groups); i++) {
96 : : nln_notifier_destroy(notifiers[i]);
97 : : }
98 : : nln_destroy(nln);
99 : : }
100 : :
101 : : /* Dump command */
102 : : static void
103 : 0 : test_nl_ct_dump(struct ovs_cmdl_context *ctx)
104 : : {
105 : : struct nl_ct_dump_state *dump;
106 : 0 : uint16_t zone, *pzone = NULL;
107 : : struct ct_dpif_entry entry;
108 : : int err;
109 : :
110 [ # # ]: 0 : if (ctx->argc >= 2) {
111 [ # # ]: 0 : if (!ovs_scan(ctx->argv[1], "zone=%"SCNu16, &zone)) {
112 : 0 : ovs_fatal(0, "Error parsing zone= specifier");
113 : : }
114 : 0 : pzone = &zone;
115 : : }
116 : 0 : err = nl_ct_dump_start(&dump, pzone);
117 [ # # ]: 0 : if (err) {
118 : 0 : ovs_fatal(err, "Error creating conntrack netlink dump");
119 : : }
120 : :
121 : : do {
122 : 0 : err = nl_ct_dump_next(dump, &entry);
123 [ # # ]: 0 : if (!err) {
124 : 0 : struct ds ds = DS_EMPTY_INITIALIZER;
125 : :
126 : 0 : ct_dpif_format_entry(&entry, &ds, true, true);
127 : 0 : printf("%s\n", ds_cstr(&ds));
128 : 0 : ds_destroy(&ds);
129 : : }
130 [ # # ]: 0 : } while (!err);
131 : :
132 [ # # ]: 0 : if (err != EOF) {
133 : 0 : ovs_fatal(err, "Error dumping conntrack netlink entry");
134 : : }
135 : 0 : nl_ct_dump_done(dump);
136 : 0 : }
137 : :
138 : : /* Flush command */
139 : : static void
140 : 54 : test_nl_ct_flush(struct ovs_cmdl_context *ctx OVS_UNUSED)
141 : : {
142 : : int err;
143 : :
144 [ - + ]: 54 : if (ctx->argc >= 2) {
145 : : uint16_t zone;
146 : :
147 [ # # ]: 0 : if (ovs_scan(ctx->argv[1], "zone=%"SCNu16, &zone)) {
148 : 0 : err = nl_ct_flush_zone(zone);
149 : : } else {
150 : 0 : ovs_fatal(0, "Error parsing zone= specifier");
151 : : }
152 : : } else {
153 : 54 : err = nl_ct_flush();
154 : : }
155 [ - + ]: 54 : if (err) {
156 : 0 : ovs_fatal(err, "Error flushing conntrack netlink");
157 : : }
158 : 54 : }
159 : :
160 : : static const struct ovs_cmdl_command commands[] = {
161 : : /* Linux netlink connection tracker interface test. */
162 : :
163 : : /* Prints all the entries in the connection table and exits. */
164 : : {"dump", "[zone=zone]", 0, 1, test_nl_ct_dump, OVS_RO},
165 : : /* Listens to all the connection tracking events and prints them to
166 : : * standard output until killed. */
167 : : {"monitor", "", 0, 0, test_nl_ct_monitor, OVS_RO},
168 : : /* Flushes all the entries from all the tables.. */
169 : : {"flush", "[zone=zone]", 0, 1, test_nl_ct_flush, OVS_RO},
170 : :
171 : : {NULL, NULL, 0, 0, NULL, OVS_RO},
172 : : };
173 : :
174 : : static void
175 : 54 : test_netlink_conntrack(int argc, char *argv[])
176 : : {
177 : 162 : struct ovs_cmdl_context ctx = {
178 : 54 : .argc = argc - 1,
179 : 54 : .argv = argv + 1,
180 : : };
181 : 54 : set_program_name(argv[0]);
182 : 54 : ovs_cmdl_run_command(&ctx, commands);
183 : 54 : }
184 : :
185 : 1282 : OVSTEST_REGISTER("test-netlink-conntrack", test_netlink_conntrack);
|