Skip to content

Commit

Permalink
Basic tfw_sched_match implementation
Browse files Browse the repository at this point in the history
- Scheduler modules are moved to sub-directories to group their files.
- tfw_sched_match implements "prefix" and "equal" comparisons.
- tfw_sched_match has a sysctl interface with a tiny config parser.

Related to task:
#5 - Load balancing
  • Loading branch information
vdmit11 committed Oct 1, 2014
1 parent 5eb6fcf commit 0754b4a
Show file tree
Hide file tree
Showing 18 changed files with 1,426 additions and 254 deletions.
4 changes: 2 additions & 2 deletions tempesta.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
SSOCKET=sync_socket
TDB=tempesta_db
TFW=tempesta_fw
SCHED=tfw_sched_dummy
SCHED=tfw_sched_match
TFW_ROOT=`pwd`/$TFW
TFW_CACHE_SIZE=`expr 256 \* 1024`
TFW_CACHE_PATH=$TFW_ROOT/cache
Expand Down Expand Up @@ -45,7 +45,7 @@ start()
cache_path="$TFW_CACHE_PATH"
[ $? -ne 0 ] && error "cannot load tempesta module"

insmod $TFW_ROOT/sched/$SCHED.ko
insmod $TFW_ROOT/sched/match/$SCHED.ko
[ $? -ne 0 ] && error "cannot load scheduler module"

sysctl --load=tempesta.sysctl.conf
Expand Down
238 changes: 0 additions & 238 deletions tempesta_fw/if.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,251 +20,13 @@
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/ctype.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/sysctl.h>

#include "tempesta.h"
#include "cache.h"
#include "lib.h"
#include "log.h"

/*
* ------------------------------------------------------------------------
* Helping routines
* ------------------------------------------------------------------------
*/
/**
* Retrurn number of tokens in @str separated by space ([ \t]+).
* @str is null-terminated string.
*/
static int
tfw_str_tokens_count(const char *str)
{
int n = 0;

/* Eat empty string prefix. */
while (*str == ' ' || *str == '\t')
++str;

while (*str) {
++n;
/* Eat a word. */
while (*str && *str != ' ' && *str != '\t')
++str;
/* Eat all separators. */
while (*str && (*str == ' ' || *str == '\t'))
++str;
}

return n;
}

static int
tfw_inet_pton_ipv4(char **p, struct sockaddr_in *addr)
{
int octet = -1, i = 0, port = 0;
unsigned char *a = (unsigned char *)&addr->sin_addr.s_addr;

addr->sin_family = AF_INET;
addr->sin_addr.s_addr = 0;
for ( ; **p && !isspace(**p); ++*p) {
if (isdigit(**p)) {
octet = (octet == -1)
? **p - '0'
: octet * 10 + **p - '0';
if ((!port && octet > 255) || octet > 0xFFFF)
return -EINVAL;
}
else if (octet >= 0 && ((**p == '.' && i < 4)
|| (**p == ':' && i == 3)))
{
a[i++] = octet;
octet = -1;
port = **p == ':';
} else
return -EINVAL;
}
if (octet >= 0) {
if (i == 3) {
/* Default port. */
a[i] = octet;
addr->sin_port = htons(DEF_PORT);
return 0;
}
else if (i == 4) {
addr->sin_port = htons(octet);
return 0;
}
}

return -EINVAL;
}

static int
tfw_inet_pton_ipv6(char **p, struct sockaddr_in6 *addr)
{
#define XD(x) ((x >= 'a') ? 10 + x - 'a' : x - '0')

int words[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
int a, hole = -1, i = 0, port = -1, ipv4_mapped = 0;

memset(addr, 0, sizeof(*addr));
addr->sin6_family = AF_INET6;

for ( ; **p && !isspace(**p); ++*p) {
if (i > 7 && !(i == 8 && port == 1))
return -EINVAL;
if (**p == '[') {
port = 0;
}
else if (**p == ':') {
if (*(*p + 1) == ':') {
/*
* Leave current (if empty) or next (otherwise)
* word as a hole.
*/
++*p;
hole = (words[i] != -1) ? ++i : i;
} else if (words[i] == -1) {
return -EINVAL;
}
/* Store port in the last word. */
i = (port == 1) ? 8 : i + 1;
}
else if (**p == '.') {
++i;
if (ipv4_mapped)
continue;
if (words[0] != -1 || words[1] != 0xFFFF
|| words[2] == -1 || i != 3 || hole != 0)
return -EINVAL;
/*
* IPv4 mapped address.
* Recalculate the first 2 hexademical octets from to
* 1 decimal octet.
*/
addr->sin6_family = AF_INET;
words[0] = ((words[2] & 0xF000) >> 12) * 1000
+ ((words[2] & 0x0F00) >> 8) * 100
+ ((words[2] & 0x00F0) >> 4) * 10
+ (words[2] & 0x000F);
if (words[0] > 255)
return -EINVAL;
ipv4_mapped = 1;
i = 1;
words[1] = words[2] = -1;
}
else if (isxdigit(**p)) {
words[i] = words[i] == -1 ? 0 : words[i];
if (ipv4_mapped || port == 1) {
if (!isdigit(**p))
return -EINVAL;
words[i] = words[i] * 10 + **p - '0';
if (port) {
if (words[i] > 0xFFFF)
return -EINVAL;
}
else if (ipv4_mapped && words[i] > 255) {
return -EINVAL;
}
} else {
words[i] = (words[i] << 4) | XD(tolower(**p));
if (words[i] > 0xFFFF)
return -EINVAL;
}
}
else if (**p == ']') {
port = 1;
}
else
return -EINVAL;
}

/* Some sanity checks. */
if (!port || (port != -1 && words[8] <= 0)
|| (ipv4_mapped && hole == -1)
|| (ipv4_mapped && port == -1 && i != 3)
|| (port == 1 && i != 8)
|| (port == -1 && i < 7 && hole == -1))
return -EINVAL;

/* Copy parsed address. */
if (ipv4_mapped) {
struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
for (i = 0; i < 4; ++i)
addr4->sin_addr.s_addr |= words[i] << (3 - i) * 8;
} else {
for (i = a = 7; i >= 0 && a >= 0; ) {
if (words[i] == -1) {
if (i > hole)
--i;
else
if (a-- == i && i)
--i;
} else
addr->sin6_addr.s6_addr16[a--]
= htons(words[i--]);
}
}

/* Set port. */
if (port == -1) {
addr->sin6_port = htons(DEF_PORT);
return 0;
}
addr->sin6_port = htons(words[8]);

return 0;
#undef XD
}

/**
* Parse IPv4 and IPv6 addresses with optional port.
* See RFC5952.
*
* @p - string pointer, updated by the function.
* @addr - distination to write as a pointer to a union of sockaddr_in and
* sockaddr_in6.
*/
static int
tfw_inet_pton(char **p, void *addr)
{
int mode = 0;

/* Eat empty string prefix. */
while (**p && isspace(**p))
++*p;

/* Determine type of the address (IPv4/IPv6). */
if (**p == '[' || isalpha(**p)) {
mode = 6;
} else {
char *p1 = *p;
while (*p1 && isdigit(*p1))
p1++;
if (*p1 == ':') {
mode = 6;
}
else if (*p1 == '.') {
mode = 4;
}
else {
TFW_ERR("bad string: %s\n", *p);
return -EINVAL;
}
}

if (mode == 4)
return tfw_inet_pton_ipv4(p, addr);
if (mode == 6)
return tfw_inet_pton_ipv6(p, addr);

TFW_ERR("Can't parse address %s\n", *p);
return -EINVAL;
}

/*
* ------------------------------------------------------------------------
* Sysctl and /proc interfaces
Expand Down
Loading

0 comments on commit 0754b4a

Please sign in to comment.