source: src/router/quagga/nhrpd/nhrp_vc.c @ 31640

Last change on this file since 31640 was 31640, checked in by brainslayer, 4 months ago

update quagga

File size: 4.8 KB
Line 
1/* NHRP virtual connection
2 * Copyright (c) 2014-2015 Timo TerÀs
3 *
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include "zebra.h"
11#include "memory.h"
12#include "stream.h"
13#include "hash.h"
14#include "thread.h"
15#include "jhash.h"
16
17#include "nhrpd.h"
18#include "os.h"
19
20struct child_sa {
21        uint32_t id;
22        struct nhrp_vc *vc;
23        struct list_head childlist_entry;
24};
25
26static struct hash *nhrp_vc_hash;
27static struct list_head childlist_head[512];
28
29static unsigned int nhrp_vc_key(void *peer_data)
30{
31        struct nhrp_vc *vc = peer_data;
32        return jhash_2words(
33                sockunion_hash(&vc->local.nbma),
34                sockunion_hash(&vc->remote.nbma),
35                0);
36}
37
38static int nhrp_vc_cmp(const void *cache_data, const void *key_data)
39{
40        const struct nhrp_vc *a = cache_data;
41        const struct nhrp_vc *b = key_data;
42        return  sockunion_same(&a->local.nbma, &b->local.nbma) &&
43                sockunion_same(&a->remote.nbma, &b->remote.nbma);
44}
45
46static void *nhrp_vc_alloc(void *data)
47{
48        struct nhrp_vc *vc, *key = data;
49
50        vc = XMALLOC(MTYPE_NHRP_VC, sizeof(struct nhrp_vc));
51        if (vc) {
52                *vc = (struct nhrp_vc) {
53                        .local.nbma = key->local.nbma,
54                        .remote.nbma = key->remote.nbma,
55                        .notifier_list = NOTIFIER_LIST_INITIALIZER(&vc->notifier_list),
56                };
57        }
58
59        return vc;
60}
61
62static void nhrp_vc_free(void *data)
63{
64        XFREE(MTYPE_NHRP_VC, data);
65}
66
67struct nhrp_vc *nhrp_vc_get(const union sockunion *src, const union sockunion *dst, int create)
68{
69        struct nhrp_vc key;
70        key.local.nbma = *src;
71        key.remote.nbma = *dst;
72        return hash_get(nhrp_vc_hash, &key, create ? nhrp_vc_alloc : 0);
73}
74
75static void nhrp_vc_check_delete(struct nhrp_vc *vc)
76{
77        if (vc->updating || vc->ipsec || notifier_active(&vc->notifier_list))
78                return;
79        hash_release(nhrp_vc_hash, vc);
80        nhrp_vc_free(vc);
81}
82
83static void nhrp_vc_update(struct nhrp_vc *vc, long cmd)
84{
85        vc->updating = 1;
86        notifier_call(&vc->notifier_list, cmd);
87        vc->updating = 0;
88        nhrp_vc_check_delete(vc);
89}
90
91static void nhrp_vc_ipsec_reset(struct nhrp_vc *vc)
92{
93        vc->local.id[0] = 0;
94        vc->local.certlen = 0;
95        vc->remote.id[0] = 0;
96        vc->remote.certlen = 0;
97}
98
99int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
100{
101        char buf[2][SU_ADDRSTRLEN];
102        struct child_sa *sa = NULL, *lsa;
103        uint32_t child_hash = child_id % ZEBRA_NUM_OF(childlist_head);
104        int abort_migration = 0;
105
106        list_for_each_entry(lsa, &childlist_head[child_hash], childlist_entry) {
107                if (lsa->id == child_id) {
108                        sa = lsa;
109                        break;
110                }
111        }
112
113        if (!sa) {
114                if (!vc) return 0;
115
116                sa = XMALLOC(MTYPE_NHRP_VC, sizeof(struct child_sa));
117                if (!sa) return 0;
118
119                *sa = (struct child_sa) {
120                        .id = child_id,
121                        .childlist_entry = LIST_INITIALIZER(sa->childlist_entry),
122                        .vc = NULL,
123                };
124                list_add_tail(&sa->childlist_entry, &childlist_head[child_hash]);
125        }
126
127        if (sa->vc == vc)
128                return 0;
129
130        if (vc) {
131                /* Attach first to new VC */
132                vc->ipsec++;
133                nhrp_vc_update(vc, NOTIFY_VC_IPSEC_CHANGED);
134        }
135        if (sa->vc && vc) {
136                /* Notify old VC of migration */
137                sa->vc->abort_migration = 0;
138                debugf(NHRP_DEBUG_COMMON, "IPsec NBMA change of %s to %s",
139                        sockunion2str(&sa->vc->remote.nbma, buf[0], sizeof buf[0]),
140                        sockunion2str(&vc->remote.nbma, buf[1], sizeof buf[1]));
141                nhrp_vc_update(sa->vc, NOTIFY_VC_IPSEC_UPDATE_NBMA);
142                abort_migration = sa->vc->abort_migration;
143        }
144        if (sa->vc) {
145                /* Deattach old VC */
146                sa->vc->ipsec--;
147                if (!sa->vc->ipsec) nhrp_vc_ipsec_reset(sa->vc);
148                nhrp_vc_update(sa->vc, NOTIFY_VC_IPSEC_CHANGED);
149        }
150
151        /* Update */
152        sa->vc = vc;
153        if (!vc) {
154                list_del(&sa->childlist_entry);
155                XFREE(MTYPE_NHRP_VC, sa);
156        }
157
158        return abort_migration;
159}
160
161void nhrp_vc_notify_add(struct nhrp_vc *vc, struct notifier_block *n, notifier_fn_t action)
162{
163        notifier_add(n, &vc->notifier_list, action);
164}
165
166void nhrp_vc_notify_del(struct nhrp_vc *vc, struct notifier_block *n)
167{
168        notifier_del(n);
169        nhrp_vc_check_delete(vc);
170}
171
172
173struct nhrp_vc_iterator_ctx {
174        void (*cb)(struct nhrp_vc *, void *);
175        void *ctx;
176};
177
178static void nhrp_vc_iterator(struct hash_backet *b, void *ctx)
179{
180        struct nhrp_vc_iterator_ctx *ic = ctx;
181        ic->cb(b->data, ic->ctx);
182}
183
184void nhrp_vc_foreach(void (*cb)(struct nhrp_vc *, void *), void *ctx)
185{
186        struct nhrp_vc_iterator_ctx ic = {
187                .cb = cb,
188                .ctx = ctx,
189        };
190        hash_iterate(nhrp_vc_hash, nhrp_vc_iterator, &ic);
191}
192
193void nhrp_vc_init(void)
194{
195        size_t i;
196
197        nhrp_vc_hash = hash_create(nhrp_vc_key, nhrp_vc_cmp);
198        for (i = 0; i < ZEBRA_NUM_OF(childlist_head); i++)
199                list_init(&childlist_head[i]);
200}
201
202void nhrp_vc_reset(void)
203{
204        struct child_sa *sa, *n;
205        size_t i;
206
207        for (i = 0; i < ZEBRA_NUM_OF(childlist_head); i++) {
208                list_for_each_entry_safe(sa, n, &childlist_head[i], childlist_entry)
209                        nhrp_vc_ipsec_updown(sa->id, 0);
210        }
211}
212
213void nhrp_vc_terminate(void)
214{
215        nhrp_vc_reset();
216        hash_clean(nhrp_vc_hash, nhrp_vc_free);
217}
Note: See TracBrowser for help on using the repository browser.