diff options
| author | Sander Vrijders <sander.vrijders@ugent.be> | 2017-09-21 14:58:07 +0000 | 
|---|---|---|
| committer | dimitri staessens <dimitri.staessens@ugent.be> | 2017-09-21 14:58:07 +0000 | 
| commit | e2d3b18ab787ebe090cd958cc63be655be86f42c (patch) | |
| tree | a51f0260c4445ddf35fb190e605704669e84bb94 /src/ipcpd | |
| parent | e5336f1309c42da770ef7aa603b463ad4d24e2c9 (diff) | |
| parent | f6071ecf0cd3768eaed9a847f676433c120ea89e (diff) | |
| download | ouroboros-e2d3b18ab787ebe090cd958cc63be655be86f42c.tar.gz ouroboros-e2d3b18ab787ebe090cd958cc63be655be86f42c.zip | |
Merged in sandervrijders/ouroboros/be-lfa-pff (pull request #607)
ipcpd: normal: Add alternate hop PFF
Diffstat (limited to 'src/ipcpd')
| -rw-r--r-- | src/ipcpd/normal/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/ipcpd/normal/addr_auth.c | 2 | ||||
| -rw-r--r-- | src/ipcpd/normal/pff.c | 13 | ||||
| -rw-r--r-- | src/ipcpd/normal/pol/alternate_pff.c | 402 | ||||
| -rw-r--r-- | src/ipcpd/normal/pol/alternate_pff.h | 61 | ||||
| -rw-r--r-- | src/ipcpd/normal/pol/simple_pff.c | 14 | ||||
| -rw-r--r-- | src/ipcpd/normal/routing.c | 2 | 
7 files changed, 482 insertions, 13 deletions
| diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt index ebb413a8..8dbe4820 100644 --- a/src/ipcpd/normal/CMakeLists.txt +++ b/src/ipcpd/normal/CMakeLists.txt @@ -41,6 +41,7 @@ set(SOURCE_FILES    routing.c    sdu_sched.c    # Add policies last +  pol/alternate_pff.c    pol/flat.c    pol/link_state.c    pol/graph.c diff --git a/src/ipcpd/normal/addr_auth.c b/src/ipcpd/normal/addr_auth.c index c7c744c7..d438f98f 100644 --- a/src/ipcpd/normal/addr_auth.c +++ b/src/ipcpd/normal/addr_auth.c @@ -36,7 +36,7 @@ int addr_auth_init(enum pol_addr_auth type,                     const void *       info)  {          switch (type) { -        case FLAT_RANDOM: +        case ADDR_AUTH_FLAT_RANDOM:                  ops = &flat_ops;                  break;          default: diff --git a/src/ipcpd/normal/pff.c b/src/ipcpd/normal/pff.c index 27ff17f7..3d114aa1 100644 --- a/src/ipcpd/normal/pff.c +++ b/src/ipcpd/normal/pff.c @@ -24,6 +24,7 @@  #include "pff.h"  #include "pol-pff-ops.h" +#include "pol/alternate_pff.h"  #include "pol/simple_pff.h"  struct pff { @@ -40,16 +41,20 @@ struct pff * pff_create(enum pol_pff pol)                  return NULL;          switch (pol) { -        case SIMPLE_PFF: +        case PFF_ALTERNATE: +                pff->ops = &alternate_pff_ops; +                break; +        case PFF_SIMPLE:                  pff->ops = &simple_pff_ops; -                pff->pff_i = pff->ops->create(); -                if (pff->pff_i == NULL) -                        goto err;                  break;          default:                  goto err;          } +        pff->pff_i = pff->ops->create(); +        if (pff->pff_i == NULL) +                goto err; +          return pff;   err:          free(pff); diff --git a/src/ipcpd/normal/pol/alternate_pff.c b/src/ipcpd/normal/pol/alternate_pff.c new file mode 100644 index 00000000..3952bc82 --- /dev/null +++ b/src/ipcpd/normal/pol/alternate_pff.c @@ -0,0 +1,402 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Policy for PFF with alternate next hops + * + *    Dimitri Staessens <dimitri.staessens@ugent.be> + *    Sander Vrijders   <sander.vrijders@ugent.be> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#define _POSIX_C_SOURCE 200112L + +#include "config.h" + +#include <ouroboros/hashtable.h> +#include <ouroboros/errno.h> +#include <ouroboros/list.h> + +#include <string.h> +#include <assert.h> +#include <pthread.h> + +#include "alternate_pff.h" + +struct nhop { +        struct list_head next; +        int              fd; +}; + +struct addr { +        struct list_head next; +        uint64_t         addr; +}; + +struct pff_i { +        struct htable *  table; + +        struct list_head addrs; + +        struct list_head nhops_down; + +        pthread_rwlock_t lock; +}; + +struct pol_pff_ops alternate_pff_ops = { +        .create            = alternate_pff_create, +        .destroy           = alternate_pff_destroy, +        .lock              = alternate_pff_lock, +        .unlock            = alternate_pff_unlock, +        .add               = alternate_pff_add, +        .update            = alternate_pff_update, +        .del               = alternate_pff_del, +        .flush             = alternate_pff_flush, +        .nhop              = alternate_pff_nhop, +        .flow_state_change = alternate_flow_state_change +}; + +static int add_addr(struct pff_i * pff_i, +                    uint64_t       addr) +{ +        struct addr * a; + +        a = malloc(sizeof(*a)); +        if (a == NULL) +                return -1; + +        a->addr = addr; + +        list_add(&a->next, &(pff_i->addrs)); + +        return 0; +} + +static void del_addr(struct pff_i * pff_i, +                     uint64_t       addr) +{ +        struct list_head * pos = NULL; +        struct list_head * n   = NULL; + +        list_for_each_safe(pos, n, &(pff_i->addrs)) { +                struct addr * e = list_entry(pos, struct addr, next); +                if (e->addr == addr) { +                        list_del(&e->next); +                        free(e); +                        return; +                } +        } +} + +static void del_addrs(struct pff_i * pff_i) +{ +        struct list_head * pos = NULL; +        struct list_head * n   = NULL; + +        list_for_each_safe(pos, n, &(pff_i->addrs)) { +                struct addr * e = list_entry(pos, struct addr, next); +                list_del(&e->next); +                free(e); +        } +} + +static void del_nhops_down(struct pff_i * pff_i) +{ +        struct list_head * pos = NULL; +        struct list_head * n   = NULL; + +        list_for_each_safe(pos, n, &(pff_i->nhops_down)) { +                struct nhop * e = list_entry(pos, struct nhop, next); +                list_del(&e->next); +                free(e); +        } +} + +static int del_nhop_down(struct pff_i * pff_i, +                         int            fd) +{ +        struct list_head * pos = NULL; +        struct list_head * n   = NULL; + +        list_for_each_safe(pos, n, &(pff_i->nhops_down)) { +                struct nhop * e = list_entry(pos, struct nhop, next); +                if (e->fd == fd) { +                        list_del(&e->next); +                        free(e); +                        return 0; +                } +        } + +        return -1; +} + +static int add_nhop_down(struct pff_i * pff_i, +                         int            fd) +{ +        struct nhop *      nhop; + +        nhop = malloc(sizeof(*nhop)); +        if (nhop == NULL) +                return -1; + +        nhop->fd = fd; + +        list_add(&nhop->next, &(pff_i->nhops_down)); + +        return 0; +} + +static bool nhops_down_has(struct pff_i * pff_i, +                           int            fd) +{ +        struct list_head * pos = NULL; + +        list_for_each(pos, &pff_i->nhops_down) { +                struct nhop * e = list_entry(pos, struct nhop, next); +                if (e->fd == fd) +                        return true; +        } + +        return false; +} + +static int add_to_htable(struct pff_i * pff_i, +                         uint64_t       addr, +                         int *          fd, +                         size_t         len) +{ +        int * val; + +        assert(pff_i); +        assert(len > 0); + +        val = malloc(sizeof(*val) * (len + 1)); +        if (val == NULL) +                goto fail_malloc; + +        memcpy(val, fd, len * sizeof(*val)); +        /* Put primary hop again at the end */ +        val[len] = val[0]; + +        if (htable_insert(pff_i->table, addr, val, len)) +                goto fail_insert; + +        return 0; + + fail_insert: +        free(val); + fail_malloc: +        return -1; +} + +struct pff_i * alternate_pff_create(void) +{ +        struct pff_i * tmp; + +        tmp = malloc(sizeof(*tmp)); +        if (tmp == NULL) +                goto fail_malloc; + +        if (pthread_rwlock_init(&tmp->lock, NULL)) +                goto fail_lock; + +        tmp->table = htable_create(PFT_SIZE, false); +        if (tmp->table == NULL) +                goto fail_table; + +        list_head_init(&tmp->nhops_down); +        list_head_init(&tmp->addrs); + +        return tmp; + + fail_table: +        pthread_rwlock_destroy(&tmp->lock); + fail_lock: +        free(tmp); + fail_malloc: +        return NULL; +} + +void alternate_pff_destroy(struct pff_i * pff_i) +{ +        assert(pff_i); + +        htable_destroy(pff_i->table); +        del_nhops_down(pff_i); +        pthread_rwlock_destroy(&pff_i->lock); +        free(pff_i); +} + +void alternate_pff_lock(struct pff_i * pff_i) +{ +        pthread_rwlock_wrlock(&pff_i->lock); +} + +void alternate_pff_unlock(struct pff_i * pff_i) +{ +        pthread_rwlock_unlock(&pff_i->lock); +} + +int alternate_pff_add(struct pff_i * pff_i, +                      uint64_t       addr, +                      int *          fd, +                      size_t         len) +{ +        assert(pff_i); +        assert(len > 0); + +        if (add_to_htable(pff_i, addr, fd, len)) +                return -1; + +        if (add_addr(pff_i, addr)) { +                htable_delete(pff_i->table, addr); +                return -1; +        } + +        return 0; +} + +int alternate_pff_update(struct pff_i * pff_i, +                         uint64_t       addr, +                         int *          fd, +                         size_t         len) +{ +        assert(pff_i); +        assert(len > 0); + +        if (htable_delete(pff_i->table, addr)) +                return -1; + +        if (add_to_htable(pff_i, addr, fd, len)) +                return -1; + +        return 0; +} + +int alternate_pff_del(struct pff_i * pff_i, +                      uint64_t       addr) +{ +        assert(pff_i); + +        del_addr(pff_i, addr); + +        if (htable_delete(pff_i->table, addr)) +                return -1; + +        return 0; +} + +void alternate_pff_flush(struct pff_i * pff_i) +{ +        assert(pff_i); + +        htable_flush(pff_i->table); + +        del_nhops_down(pff_i); + +        del_addrs(pff_i); +} + +int alternate_pff_nhop(struct pff_i * pff_i, +                       uint64_t       addr) +{ +        int    fd = -1; +        size_t len; +        void * el; + +        assert(pff_i); + +        pthread_rwlock_rdlock(&pff_i->lock); + +        if (htable_lookup(pff_i->table, addr, &el, &len)) { +                pthread_rwlock_unlock(&pff_i->lock); +                return -1; +        } + +        fd = *((int *) el); + +        pthread_rwlock_unlock(&pff_i->lock); + +        return fd; +} + +int alternate_flow_state_change(struct pff_i * pff_i, +                                int            fd, +                                bool           up) +{ +        struct list_head * pos = NULL; +        size_t             len; +        void *             el; +        int *              fds; +        size_t             i; +        int                tmp; + +        assert(pff_i); + +        pthread_rwlock_wrlock(&pff_i->lock); + +        if (up) { +                if (del_nhop_down(pff_i, fd)) { +                        pthread_rwlock_unlock(&pff_i->lock); +                        return -1; +                } +        } else { +                if (add_nhop_down(pff_i, fd)) { +                        pthread_rwlock_unlock(&pff_i->lock); +                        return -1; +                } +        } + +        list_for_each(pos, &pff_i->addrs) { +                struct addr * e = list_entry(pos, struct addr, next); +                if (htable_lookup(pff_i->table, e->addr, &el, &len)) { +                        pthread_rwlock_unlock(&pff_i->lock); +                        return -1; +                } + +                fds = (int *) el; + +                if (up) { +                        /* It is using an alternate */ +                        if (fds[len] == fd && fds[0] != fd) { +                                for (i = 0 ; i < len; i++) { +                                        /* Found the primary */ +                                        if (fds[i] == fd) { +                                                tmp = fds[0]; +                                                fds[0] = fds[i]; +                                                fds[i] = tmp; +                                                break; +                                        } +                                } +                        } +                } else { +                        /* Need to switch to a (different) alternate */ +                        if (fds[0] == fd) { +                                for (i = 0 ; i < len; i++) { +                                        /* Usable alternate */ +                                        if (!nhops_down_has(pff_i, fds[i])) { +                                                tmp = fds[0]; +                                                fds[0] = fds[i]; +                                                fds[i] = tmp; +                                                break; +                                        } +                                } +                        } +                } +        } + +        pthread_rwlock_unlock(&pff_i->lock); + +        return 0; +} diff --git a/src/ipcpd/normal/pol/alternate_pff.h b/src/ipcpd/normal/pol/alternate_pff.h new file mode 100644 index 00000000..8fa2d514 --- /dev/null +++ b/src/ipcpd/normal/pol/alternate_pff.h @@ -0,0 +1,61 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Policy for PFF with alternate next hops + * + *    Dimitri Staessens <dimitri.staessens@ugent.be> + *    Sander Vrijders   <sander.vrijders@ugent.be> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#ifndef OUROBOROS_IPCPD_NORMAL_ALTERNATE_PFF_H +#define OUROBOROS_IPCPD_NORMAL_ALTERNATE_PFF_H + +#include "pol-pff-ops.h" + +struct pff_i * alternate_pff_create(void); + +void           alternate_pff_destroy(struct pff_i * pff_i); + +void           alternate_pff_lock(struct pff_i * pff_i); + +void           alternate_pff_unlock(struct pff_i * pff_i); + +int            alternate_pff_add(struct pff_i * pff_i, +                                 uint64_t       addr, +                                 int *          fd, +                                 size_t         len); + +int            alternate_pff_update(struct pff_i * pff_i, +                                    uint64_t       addr, +                                    int *          fd, +                                    size_t         len); + +int            alternate_pff_del(struct pff_i * pff_i, +                                 uint64_t       addr); + +void           alternate_pff_flush(struct pff_i * pff_i); + +/* Returns fd towards next hop */ +int            alternate_pff_nhop(struct pff_i * pff_i, +                                  uint64_t       addr); + +int            alternate_flow_state_change(struct pff_i * pff_i, +                                           int            fd, +                                           bool           up); + +struct pol_pff_ops alternate_pff_ops; + +#endif /* OUROBOROS_IPCPD_NORMAL_ALTERNATE_PFF_H */ diff --git a/src/ipcpd/normal/pol/simple_pff.c b/src/ipcpd/normal/pol/simple_pff.c index 28f7aa2e..7af4663c 100644 --- a/src/ipcpd/normal/pol/simple_pff.c +++ b/src/ipcpd/normal/pol/simple_pff.c @@ -109,7 +109,7 @@ int simple_pff_add(struct pff_i * pff_i,          *val = fd[0]; -        if (htable_insert(pff_i->table, addr, val)) { +        if (htable_insert(pff_i->table, addr, val, 1)) {                  free(val);                  return -1;          } @@ -137,7 +137,7 @@ int simple_pff_update(struct pff_i * pff_i,                  return -1;          } -        if (htable_insert(pff_i->table, addr, val)) { +        if (htable_insert(pff_i->table, addr, val, 1)) {                  free(val);                  return -1;          } @@ -166,16 +166,16 @@ void simple_pff_flush(struct pff_i * pff_i)  int simple_pff_nhop(struct pff_i * pff_i,                      uint64_t       addr)  { -        int * j; -        int   fd = -1; +        void * j; +        size_t len; +        int    fd = -1;          assert(pff_i);          pthread_rwlock_rdlock(&pff_i->lock); -        j = (int *) htable_lookup(pff_i->table, addr); -        if (j != NULL) -                fd = *j; +        if (!htable_lookup(pff_i->table, addr, &j, &len)) +                fd = *((int *) j);          pthread_rwlock_unlock(&pff_i->lock); diff --git a/src/ipcpd/normal/routing.c b/src/ipcpd/normal/routing.c index 47ce3518..afef23a2 100644 --- a/src/ipcpd/normal/routing.c +++ b/src/ipcpd/normal/routing.c @@ -32,7 +32,7 @@ struct pol_routing_ops * r_ops;  int routing_init(enum pol_routing pr)  {          switch (pr) { -        case LINK_STATE: +        case ROUTING_LINK_STATE:                  r_ops = &link_state_ops;                  break;          default: | 
