blob: d83102cee34ed0b174c202e52e2e44b3cdfebf88 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001--- a/libiptc/libiptc.c
2+++ b/libiptc/libiptc.c
3@@ -2505,6 +2505,224 @@ static void counters_map_set(STRUCT_COUN
4 DEBUGP_C("SET\n");
5 }
6
7+#define FASTPATH
8+
9+#ifdef FASTPATH
10+#include <stdio.h>
11+#include <stdlib.h>
12+#include <errno.h>
13+#include <unistd.h>
14+#include <poll.h>
15+#include <string.h>
16+#include <fcntl.h>
17+#include <sys/types.h>
18+#include <sys/stat.h>
19+#include <sys/statfs.h>
20+#include <sys/socket.h>
21+#include <sys/types.h>
22+#include <signal.h>
23+#include <linux/magic.h>
24+#include <linux/genetlink.h>
25+
26+/*
27+ * Generic macros for dealing with netlink sockets. Might be duplicated
28+ * elsewhere. It is recommended that commercial grade applications use
29+ * libnl or libnetlink and use the interfaces provided by the library
30+ */
31+#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
32+#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
33+#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
34+
35+static bool proc_file_exists(const char *filename)
36+{
37+ struct stat s;
38+ struct statfs f;
39+
40+ if (lstat(filename, &s))
41+ return false;
42+ if (!S_ISREG(s.st_mode))
43+ return false;
44+ if (statfs(filename, &f))
45+ return false;
46+ if (f.f_type != PROC_SUPER_MAGIC)
47+ return false;
48+ return true;
49+}
50+
51+static int create_nl_socket(int protocol, int groups)
52+{
53+ socklen_t addr_len;
54+ int fd;
55+ struct sockaddr_nl local;
56+
57+ fd = socket(AF_NETLINK, SOCK_RAW, protocol);
58+ if (fd < 0) {
59+ perror("socket");
60+ return -1;
61+ }
62+
63+ memset(&local, 0, sizeof(local));
64+ local.nl_family = AF_NETLINK;
65+ local.nl_groups = groups;
66+ if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0)
67+ goto error;
68+
69+ return fd;
70+error:
71+ close(fd);
72+ return -1;
73+}
74+
75+/*
76+ * Send netlink message to kernel
77+ */
78+int sendto_fd(int s, const char *buf, int bufLen)
79+{
80+ struct sockaddr_nl nladdr;
81+ int r;
82+
83+ memset(&nladdr, 0, sizeof(nladdr));
84+ nladdr.nl_family = AF_NETLINK;
85+
86+ while ((r = sendto(s, buf, bufLen, 0, (struct sockaddr *) &nladdr,
87+ sizeof(nladdr))) < bufLen) {
88+ if (r > 0) {
89+ buf += r;
90+ bufLen -= r;
91+ } else if (errno != EAGAIN) {
92+ return -1;
93+ }
94+ }
95+
96+ return 0;
97+}
98+
99+/*
100+ * Probe the controller in genetlink to find the family id
101+ * for the CONTROL_EXMPL family
102+ */
103+int get_family_id(int sd)
104+{
105+ struct {
106+ struct nlmsghdr n;
107+ struct genlmsghdr g;
108+ char buf[256];
109+ } family_req;
110+
111+ struct {
112+ struct nlmsghdr n;
113+ struct genlmsghdr g;
114+ char buf[256];
115+ } ans;
116+
117+ int id;
118+ struct nlattr *na;
119+ int rep_len;
120+
121+ /* Get family name */
122+ family_req.n.nlmsg_type = GENL_ID_CTRL;
123+ family_req.n.nlmsg_flags = NLM_F_REQUEST;
124+ family_req.n.nlmsg_seq = 0;
125+ family_req.n.nlmsg_pid = getpid();
126+ family_req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
127+ family_req.g.cmd = CTRL_CMD_GETFAMILY;
128+ family_req.g.version = 0x1;
129+
130+ na = (struct nlattr *) GENLMSG_DATA(&family_req);
131+ na->nla_type = CTRL_ATTR_FAMILY_NAME;
132+
133+ /*------change here--------*/
134+ na->nla_len = strlen("FASTPATH") + 1 + NLA_HDRLEN;
135+ strcpy(NLA_DATA(na), "FASTPATH");
136+
137+ family_req.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
138+
139+ if (sendto_fd(sd, (char *) &family_req, family_req.n.nlmsg_len) < 0)
140+ return -1;
141+
142+ rep_len = recv(sd, &ans, sizeof(ans), 0);
143+ if (rep_len < 0){
144+ perror("recv");
145+ return -1;
146+ }
147+
148+ /* Validate response message */
149+ if (!NLMSG_OK((&ans.n), rep_len)){
150+ fprintf(stderr, "invalid reply message\n");
151+ return -1;
152+ }
153+
154+ if (ans.n.nlmsg_type == NLMSG_ERROR) { /* error */
155+ fprintf(stderr, "received error\n");
156+ return -1;
157+ }
158+
159+ na = (struct nlattr *)GENLMSG_DATA(&ans);
160+ na = (struct nlattr *)((char *) na + NLA_ALIGN(na->nla_len));
161+ if (na->nla_type == CTRL_ATTR_FAMILY_ID) {
162+ id = *(__u16 *)NLA_DATA(na);
163+ }
164+
165+ return id;
166+}
167+
168+static int tc_commit_notify_fastpath(void)
169+{
170+ struct {
171+ struct nlmsghdr n;
172+ struct genlmsghdr g;
173+ char buf[256];
174+ } ans;
175+
176+ struct {
177+ struct nlmsghdr n;
178+ struct genlmsghdr g;
179+ char buf[256];
180+ } req;
181+
182+ struct nlattr *na;
183+ int nl_sd, id, mlength;
184+ struct sockaddr_nl nladdr;
185+ char *message = "TC_COMMIT!";
186+
187+ nl_sd = create_nl_socket(NETLINK_GENERIC,0);
188+ if (nl_sd < 0) {
189+ printf("create failure\n");
190+ return -1;
191+ }
192+
193+ id = get_family_id(nl_sd);
194+ if (id < 0) {
195+ printf("bad id\n");
196+ return -1;
197+ }
198+
199+ /* Send command needed */
200+ req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
201+ req.n.nlmsg_type = id;
202+ req.n.nlmsg_flags = NLM_F_REQUEST;
203+ req.n.nlmsg_seq = 60;
204+ req.n.nlmsg_pid = getpid();
205+ req.g.cmd = 1; //FASTPATH_NL_C_IPT_NOTIFY
206+
207+ /*compose message*/
208+ na = (struct nlattr *)GENLMSG_DATA(&req);
209+ na->nla_type = 1; //FASTPATH_NL_C_IPT_NOTIFY
210+ mlength = strlen(message);
211+ na->nla_len = mlength+NLA_HDRLEN; //message length
212+ memcpy(NLA_DATA(na), message, mlength);
213+ req.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
214+
215+ /*send message*/
216+ memset(&nladdr, 0, sizeof(nladdr));
217+ nladdr.nl_family = AF_NETLINK;
218+
219+ sendto(nl_sd, (char *)&req, req.n.nlmsg_len, 0,
220+ (struct sockaddr *)&nladdr, sizeof(nladdr));
221+ close(nl_sd);
222+ return 0;
223+}
224+#endif
225
226 int
227 TC_COMMIT(struct xtc_handle *handle)
228@@ -2672,6 +2890,11 @@ TC_COMMIT(struct xtc_handle *handle)
229 free(repl);
230 free(newcounters);
231
232+#ifdef FASTPATH
233+ if (proc_file_exists("/proc/net/fastpath"))
234+ tc_commit_notify_fastpath();
235+#endif
236+
237 finished:
238 return 1;
239