summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/input_conn.c
diff options
context:
space:
mode:
authorDeepak S <deepak.s@linux.intel.com>2017-07-13 21:26:50 -0700
committerDeepak S <deepak.s@linux.intel.com>2017-07-14 04:58:47 -0700
commit7286b2518ec8e4398b512ce95def9166a7af2e4a (patch)
treec93ef65d9e73e8893ccecb720152e16aae96a8b6 /VNFs/DPPD-PROX/input_conn.c
parentadcb79da90176b27224eeb1d00aa0e611ef85a9b (diff)
Adding PROX(Packet pROcessing eXecution engine) VNF to sampleVNF
JIRA: SAMPLEVNF-55 PROX is a DPDK-based application implementing Telco use-cases such as a simplified BRAS/BNG, light-weight AFTR... It also allows configuring finer grained network functions like QoS, Routing, load-balancing... (We are moving PROX version v039 to sampleVNF https://01.org/intel-data-plane-performance-demonstrators/prox-overview) Change-Id: Ia3cb02cf0e49ac5596e922c197ff7e010293d033 Signed-off-by: Deepak S <deepak.s@linux.intel.com>
Diffstat (limited to 'VNFs/DPPD-PROX/input_conn.c')
-rw-r--r--VNFs/DPPD-PROX/input_conn.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/input_conn.c b/VNFs/DPPD-PROX/input_conn.c
new file mode 100644
index 00000000..63e6511e
--- /dev/null
+++ b/VNFs/DPPD-PROX/input_conn.c
@@ -0,0 +1,236 @@
+/*
+// Copyright (c) 2010-2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "input_conn.h"
+#include "input.h"
+#include "run.h"
+#include "cmd_parser.h"
+
+static struct input tcp_server;
+int tcp_server_started;
+static struct input uds_server;
+int uds_server_started;
+
+/* Active clients */
+struct client_conn {
+ struct input input;
+ int enabled;
+ int n_buf;
+ char buf[32768];
+};
+
+struct client_conn clients[32];
+
+static int start_listen_tcp(void)
+{
+ struct sockaddr_in server;
+ int ret, sock;
+ int optval = 1;
+
+ memset(&server, 0, sizeof(server));
+ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if (sock == -1)
+ return -1;
+
+ server.sin_family = AF_INET;
+ server.sin_port = ntohs(8474);
+ server.sin_addr.s_addr = ntohl(INADDR_ANY);
+
+ ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
+
+ if (ret)
+ return -1;
+
+ if (bind(sock, (struct sockaddr *) &server, sizeof(server)) == -1)
+ return -1;
+
+ if (listen(sock, 1) == -1)
+ return -1;
+
+ return sock;
+}
+
+static int start_listen_uds(void)
+{
+ int sock;
+ struct sockaddr_un server = {
+ .sun_path = "/tmp/prox.sock",
+ .sun_family = AF_UNIX
+ };
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock == -1)
+ return -1;
+
+ /* Unlink can fail, i.e. when /tmp/prox.sock does not
+ exists. This is not fatal. */
+ unlink(server.sun_path);
+
+ if (bind(sock, (struct sockaddr *) &server, sizeof(server)) == -1)
+ return -1;
+
+ if (listen(sock, 1) == -1)
+ return -1;
+
+ return sock;
+}
+
+static void write_client(struct input *input, const char *buf, size_t len)
+{
+ int ret;
+
+ while ((ret = write(input->fd, buf, len)) != (int)len) {
+ buf += ret;
+ len -= ret;
+ }
+}
+
+static void handle_client(struct input* client_input)
+{
+ char cur[1024];
+ size_t i;
+ int ret;
+ struct client_conn *c = NULL;
+
+ /* Get the client structure that uses this input */
+ for (i = 0; i < sizeof(clients)/sizeof(clients[0]); ++i) {
+ if (&clients[i].input == client_input) {
+ c = &clients[i];
+ break;
+ }
+ }
+
+ /* handle_client function called non-tcp client */
+ if (c == NULL)
+ return ;
+
+ ret = read(c->input.fd, cur, sizeof(cur));
+
+ if (ret == 0) {
+ c->enabled = 0;
+ unreg_input(&c->input);
+ return ;
+ }
+
+ /* Scan in data until \n (\r skipped if followed by \n) */
+ for (int i = 0; i < ret; ++i) {
+ if (cur[i] == '\r' && i + 1 < ret && cur[i + 1] == '\n')
+ continue;
+
+ if (cur[i] == '\n') {
+ c->buf[c->n_buf] = 0;
+ if (c->n_buf)
+ cmd_parser_parse(c->buf, client_input);
+ c->n_buf = 0;
+ }
+ else if (c->n_buf + 1 < (int)sizeof(c->buf))
+ c->buf[c->n_buf++] = cur[i];
+ else
+ c->n_buf = 0;
+ }
+}
+
+static void handle_new_client(struct input* server)
+{
+ size_t i;
+
+ int new_client = accept(server->fd, NULL, NULL);
+
+ for (i = 0; i < sizeof(clients)/sizeof(clients[0]); ++i) {
+ if (clients[i].enabled == 0) {
+ break;
+ }
+ }
+
+ if (i == sizeof(clients)/sizeof(clients[0])) {
+ close(new_client);
+ return ;
+ }
+
+ clients[i].enabled = 1;
+ clients[i].n_buf = 0;
+ clients[i].input.fd = new_client;
+ clients[i].input.reply = server->reply;
+ clients[i].input.proc_input = handle_client;
+
+ reg_input(&clients[i].input);
+}
+
+int reg_input_tcp(void)
+{
+ int fd;
+
+ if (tcp_server_started)
+ return -1;
+ if ((fd = start_listen_tcp()) < 0)
+ return -1;
+
+ tcp_server.fd = fd;
+ tcp_server.proc_input = handle_new_client;
+ tcp_server.reply = write_client;
+ if (reg_input(&tcp_server) != 0) {
+ close(fd);
+ return -1;
+ }
+ tcp_server_started = 1;
+ return 0;
+}
+
+int reg_input_uds(void)
+{
+ int fd;
+
+ if (uds_server_started)
+ return -1;
+
+ if ((fd = start_listen_uds()) < 0)
+ return -1;
+
+ uds_server.fd = fd;
+ uds_server.proc_input = handle_new_client;
+ uds_server.reply = write_client;
+ if (reg_input(&uds_server) != 0) {
+ close(fd);
+ return -1;
+ }
+ uds_server_started = 1;
+ return 0;
+}
+
+void unreg_input_tcp(void)
+{
+ if (!tcp_server_started)
+ return;
+ tcp_server_started = 0;
+ close(tcp_server.fd);
+ unreg_input(&tcp_server);
+}
+
+void unreg_input_uds(void)
+{
+ if (!uds_server_started)
+ return;
+ uds_server_started = 0;
+ close(tcp_server.fd);
+ unreg_input(&tcp_server);
+}