]>
Commit | Line | Data |
---|---|---|
8f5f5e91 DS |
1 | /* |
2 | * PIM for Quagga | |
3 | * Copyright (C) 2015 Cumulus Networks, Inc. | |
4 | * Donald Sharp | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; see the file COPYING; if not, write to the | |
18 | * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | |
19 | * MA 02110-1301 USA | |
20 | */ | |
21 | #include <zebra.h> | |
22 | ||
54b97c74 | 23 | #include "log.h" |
8f5f5e91 | 24 | #include "network.h" |
744d91b3 | 25 | #include "if.h" |
8f5f5e91 DS |
26 | |
27 | #include "pimd.h" | |
75a26779 | 28 | #include "pim_vty.h" |
54b97c74 | 29 | #include "pim_str.h" |
8f5f5e91 | 30 | #include "pim_rp.h" |
ed66602c DS |
31 | #include "pim_str.h" |
32 | #include "pim_rpf.h" | |
13afbd05 | 33 | #include "pim_sock.h" |
8f5f5e91 | 34 | |
54b97c74 DS |
35 | static int i_am_rp = 0; |
36 | ||
75a26779 DS |
37 | static struct pim_rpf qpim_rp = { .rpf_addr.s_addr = INADDR_NONE }; |
38 | ||
39 | int | |
40 | pim_rp_new (const char *rp, const char *group_range) | |
41 | { | |
42 | int result; | |
43 | ||
44 | result = inet_pton (AF_INET, rp, &qpim_rp.rpf_addr.s_addr); | |
45 | if (result <= 0) | |
46 | return -1; | |
47 | ||
48 | if (!pim_rp_setup ()) | |
49 | return -2; | |
50 | ||
51 | return 0; | |
52 | } | |
53 | ||
54 | int | |
55 | pim_rp_del (const char *rp, const char *group_range) | |
56 | { | |
57 | qpim_rp.rpf_addr.s_addr = INADDR_NONE; | |
58 | ||
59 | return 0; | |
60 | } | |
13afbd05 DS |
61 | |
62 | int | |
63 | pim_rp_setup (void) | |
64 | { | |
65 | if (pim_nexthop_lookup (&qpim_rp.source_nexthop, qpim_rp.rpf_addr, NULL) != 0) | |
66 | { | |
67 | zlog_err ("Unable to lookup nexthop for rp specified"); | |
68 | return 0; | |
69 | } | |
70 | ||
13afbd05 DS |
71 | return 1; |
72 | } | |
73 | ||
54b97c74 DS |
74 | /* |
75 | * Checks to see if we should elect ourself the actual RP | |
76 | */ | |
77 | void | |
78 | pim_rp_check_rp (struct in_addr old, struct in_addr new) | |
79 | { | |
80 | if (PIM_DEBUG_ZEBRA) { | |
81 | char sold[100]; | |
82 | char snew[100]; | |
83 | char rp[100]; | |
c8ae3ce8 | 84 | pim_inet4_dump("<rp?>", qpim_rp.rpf_addr, rp, sizeof(rp)); |
54b97c74 DS |
85 | pim_inet4_dump("<old?>", old, sold, sizeof(sold)); |
86 | pim_inet4_dump("<new?>", new, snew, sizeof(snew)); | |
87 | zlog_debug("%s: %s for old %s new %s", __func__, rp, sold, snew ); | |
88 | } | |
89 | ||
c8ae3ce8 | 90 | if (qpim_rp.rpf_addr.s_addr == INADDR_NONE) |
54b97c74 DS |
91 | return; |
92 | ||
c8ae3ce8 | 93 | if (new.s_addr == qpim_rp.rpf_addr.s_addr) |
54b97c74 DS |
94 | { |
95 | i_am_rp = 1; | |
96 | return; | |
97 | } | |
98 | ||
c8ae3ce8 | 99 | if (old.s_addr == qpim_rp.rpf_addr.s_addr) |
54b97c74 DS |
100 | { |
101 | i_am_rp = 0; | |
102 | return; | |
103 | } | |
104 | } | |
105 | ||
106 | /* | |
107 | * I_am_RP(G) is true if the group-to-RP mapping indicates that | |
108 | * this router is the RP for the group. | |
109 | * | |
110 | * Since we only have static RP, all groups are part of this RP | |
111 | */ | |
112 | int | |
113 | pim_rp_i_am_rp (struct in_addr group) | |
114 | { | |
115 | return i_am_rp; | |
116 | } | |
117 | ||
71694057 DS |
118 | /* |
119 | * RP(G) | |
120 | * | |
121 | * Return the RP that the Group belongs too. | |
122 | */ | |
ed66602c | 123 | struct pim_rpf * |
71694057 DS |
124 | pim_rp_g (struct in_addr group) |
125 | { | |
126 | /* | |
127 | * For staticly configured RP, it is always the qpim_rp | |
128 | */ | |
651d0f71 | 129 | pim_nexthop_lookup(&qpim_rp.source_nexthop, qpim_rp.rpf_addr, NULL); |
ed66602c | 130 | return(&qpim_rp); |
71694057 DS |
131 | } |
132 | ||
8f5f5e91 DS |
133 | /* |
134 | * Set the upstream IP address we want to talk to based upon | |
135 | * the rp configured and the source address | |
136 | * | |
137 | * If we have don't have a RP configured and the source address is * | |
138 | * then return failure. | |
139 | * | |
140 | */ | |
141 | int | |
142 | pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source) | |
143 | { | |
c8ae3ce8 | 144 | if ((qpim_rp.rpf_addr.s_addr == INADDR_NONE) && (source.s_addr == INADDR_ANY)) |
8f5f5e91 DS |
145 | { |
146 | if (PIM_DEBUG_PIM_TRACE) | |
147 | zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); | |
148 | return 0; | |
149 | } | |
150 | ||
c8ae3ce8 | 151 | *up = (source.s_addr == INADDR_ANY) ? qpim_rp.rpf_addr : source; |
8f5f5e91 DS |
152 | |
153 | return 1; | |
154 | } | |
75a26779 DS |
155 | |
156 | int | |
157 | pim_rp_config_write (struct vty *vty) | |
158 | { | |
159 | char buffer[32]; | |
160 | ||
161 | if (qpim_rp.rpf_addr.s_addr != INADDR_NONE) | |
162 | { | |
163 | vty_out(vty, "ip pim rp %s%s", inet_ntop(AF_INET, &qpim_rp.rpf_addr, buffer, 32), VTY_NEWLINE); | |
164 | return 1; | |
165 | } | |
166 | ||
167 | return 0; | |
168 | } | |
169 | ||
170 | int | |
171 | pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) | |
172 | { | |
173 | /* | |
174 | * See if we can short-cut some? | |
175 | * This might not make sense if we ever leave a static RP | |
176 | * type of configuration. | |
177 | * Note - Premature optimization might bite our patooeys' here. | |
178 | */ | |
179 | if (I_am_RP(group)) | |
180 | { | |
181 | if (dest_addr.s_addr == qpim_rp.rpf_addr.s_addr) | |
182 | return 1; | |
183 | } | |
184 | ||
185 | if (if_lookup_exact_address (&dest_addr, AF_INET)) | |
186 | return 1; | |
187 | ||
188 | return 0; | |
189 | } |