summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/linklist.c22
-rw-r--r--lib/pbr.h29
-rw-r--r--lib/stream.c13
-rw-r--r--lib/stream.h3
-rw-r--r--lib/vrf.c39
-rw-r--r--lib/vty.c16
-rw-r--r--lib/workqueue.c3
7 files changed, 95 insertions, 30 deletions
diff --git a/lib/linklist.c b/lib/linklist.c
index 2cfa3e7482..86649dd495 100644
--- a/lib/linklist.c
+++ b/lib/linklist.c
@@ -186,26 +186,10 @@ void listnode_move_to_tail(struct list *l, struct listnode *n)
void listnode_delete(struct list *list, void *val)
{
- struct listnode *node;
+ struct listnode *node = listnode_lookup(list, val);
- assert(list);
- for (node = list->head; node; node = node->next) {
- if (node->data == val) {
- if (node->prev)
- node->prev->next = node->next;
- else
- list->head = node->next;
-
- if (node->next)
- node->next->prev = node->prev;
- else
- list->tail = node->prev;
-
- list->count--;
- listnode_free(node);
- return;
- }
- }
+ if (node)
+ list_delete_node(list, node);
}
void *listnode_head(struct list *list)
diff --git a/lib/pbr.h b/lib/pbr.h
index 1704d8d37e..90997348cf 100644
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -89,6 +89,35 @@ struct pbr_rule {
uint32_t ifindex;
};
+/* TCP flags value shared
+ * those are values of byte 13 of TCP header
+ * as mentioned in rfc793
+ */
+#define TCP_HEADER_FIN (0x01)
+#define TCP_HEADER_SYN (0x02)
+#define TCP_HEADER_RST (0x04)
+#define TCP_HEADER_PSH (0x08)
+#define TCP_HEADER_ACK (0x10)
+#define TCP_HEADER_URG (0x20)
+#define TCP_HEADER_ALL_FLAGS (TCP_HEADER_FIN | TCP_HEADER_SYN \
+ | TCP_HEADER_RST | TCP_HEADER_PSH \
+ | TCP_HEADER_ACK | TCP_HEADER_URG)
+
+/* Pbr IPTable defines
+ * those are common flags shared between BGP and Zebra
+ */
+#define MATCH_IP_SRC_SET (1 << 0)
+#define MATCH_IP_DST_SET (1 << 1)
+#define MATCH_PORT_SRC_SET (1 << 2)
+#define MATCH_PORT_DST_SET (1 << 3)
+#define MATCH_PORT_SRC_RANGE_SET (1 << 4)
+#define MATCH_PORT_DST_RANGE_SET (1 << 5)
+#define MATCH_DSCP_SET (1 << 6)
+#define MATCH_DSCP_INVERSE_SET (1 << 7)
+#define MATCH_PKT_LEN_INVERSE_SET (1 << 8)
+#define MATCH_FRAGMENT_INVERSE_SET (1 << 9)
+#define MATCH_ICMP_SET (1 << 10)
+
extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
struct pbr_rule *zrule);
diff --git a/lib/stream.c b/lib/stream.c
index aba4c20166..a172eedc99 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -1109,6 +1109,10 @@ struct stream_fifo *stream_fifo_new(void)
/* Add new stream to fifo. */
void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
{
+#if defined DEV_BUILD
+ size_t max, curmax;
+#endif
+
if (fifo->tail)
fifo->tail->next = s;
else
@@ -1116,8 +1120,15 @@ void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
fifo->tail = s;
fifo->tail->next = NULL;
-
+#if !defined DEV_BUILD
atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
+#else
+ max = atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
+ curmax = atomic_load_explicit(&fifo->max_count, memory_order_relaxed);
+ if (max > curmax)
+ atomic_store_explicit(&fifo->max_count, max,
+ memory_order_relaxed);
+#endif
}
void stream_fifo_push_safe(struct stream_fifo *fifo, struct stream *s)
diff --git a/lib/stream.h b/lib/stream.h
index e5d325e43e..11af85c663 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -115,6 +115,9 @@ struct stream_fifo {
/* number of streams in this fifo */
_Atomic size_t count;
+#if defined DEV_BUILD
+ _Atomic size_t max_count;
+#endif
struct stream *head;
struct stream *tail;
diff --git a/lib/vrf.c b/lib/vrf.c
index 797b25d01d..643ad29cf8 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -121,10 +121,10 @@ int vrf_switch_to_netns(vrf_id_t vrf_id)
/* VRF is default VRF. silently ignore */
if (!vrf || vrf->vrf_id == VRF_DEFAULT)
- return 0;
+ return 1; /* 1 = default */
/* VRF has no NETNS backend. silently ignore */
if (vrf->data.l.netns_name[0] == '\0')
- return 0;
+ return 2; /* 2 = no netns */
name = ns_netns_pathname(NULL, vrf->data.l.netns_name);
if (debug_vrf)
zlog_debug("VRF_SWITCH: %s(%u)", name, vrf->vrf_id);
@@ -505,6 +505,35 @@ void vrf_terminate(void)
}
}
+static int vrf_default_accepts_vrf(int type)
+{
+ const char *fname = NULL;
+ char buf[32] = {0x0};
+ int ret = 0;
+ FILE *fd = NULL;
+
+ /*
+ * TCP & UDP services running in the default VRF context (ie., not bound
+ * to any VRF device) can work across all VRF domains by enabling the
+ * tcp_l3mdev_accept and udp_l3mdev_accept sysctl options:
+ * sysctl -w net.ipv4.tcp_l3mdev_accept=1
+ * sysctl -w net.ipv4.udp_l3mdev_accept=1
+ */
+ if (type == SOCK_STREAM)
+ fname = "/proc/sys/net/ipv4/tcp_l3mdev_accept";
+ else if (type == SOCK_DGRAM)
+ fname = "/proc/sys/net/ipv4/udp_l3mdev_accept";
+ else
+ return ret;
+ fd = fopen(fname, "r");
+ if (fd == NULL)
+ return ret;
+ fgets(buf, 32, fd);
+ ret = atoi(buf);
+ fclose(fd);
+ return ret;
+}
+
/* Create a socket for the VRF. */
int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
char *interfacename)
@@ -515,6 +544,12 @@ int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
if (ret < 0)
zlog_err("%s: Can't switch to VRF %u (%s)", __func__, vrf_id,
safe_strerror(errno));
+ if (ret > 0 && interfacename && vrf_default_accepts_vrf(type)) {
+ zlog_err("VRF socket not used since net.ipv4.%s_l3mdev_accept != 0",
+ (type == SOCK_STREAM ? "tcp" : "udp"));
+ errno = EEXIST; /* not sure if this is the best error... */
+ return -2;
+ }
ret = socket(domain, type, protocol);
save_errno = errno;
ret2 = vrf_switchback_to_initial();
diff --git a/lib/vty.c b/lib/vty.c
index e9d1f2e323..073092dfb6 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -479,6 +479,8 @@ static int vty_command(struct vty *vty, char *buf)
const char *protocolname;
char *cp = NULL;
+ assert(vty);
+
/*
* Log non empty command lines
*/
@@ -496,13 +498,13 @@ static int vty_command(struct vty *vty, char *buf)
/* format the base vty info */
snprintf(vty_str, sizeof(vty_str), "vty[??]@%s", vty->address);
- if (vty)
- for (i = 0; i < vector_active(vtyvec); i++)
- if (vty == vector_slot(vtyvec, i)) {
- snprintf(vty_str, sizeof(vty_str),
- "vty[%d]@%s", i, vty->address);
- break;
- }
+
+ for (i = 0; i < vector_active(vtyvec); i++)
+ if (vty == vector_slot(vtyvec, i)) {
+ snprintf(vty_str, sizeof(vty_str), "vty[%d]@%s",
+ i, vty->address);
+ break;
+ }
/* format the prompt */
snprintf(prompt_str, sizeof(prompt_str), cmd_prompt(vty->node),
diff --git a/lib/workqueue.c b/lib/workqueue.c
index 1af51c06c1..39dd142afb 100644
--- a/lib/workqueue.c
+++ b/lib/workqueue.c
@@ -245,10 +245,11 @@ int work_queue_run(struct thread *thread)
char yielded = 0;
wq = THREAD_ARG(thread);
- wq->thread = NULL;
assert(wq);
+ wq->thread = NULL;
+
/* calculate cycle granularity:
* list iteration == 1 run
* listnode processing == 1 cycle