]>
Commit | Line | Data |
---|---|---|
12e41d03 DL |
1 | /* |
2 | PIM for Quagga | |
3 | Copyright (C) 2008 Everton da Silva Marques | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, but | |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; see the file COPYING; if not, write to the | |
17 | Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | |
18 | MA 02110-1301 USA | |
12e41d03 DL |
19 | */ |
20 | ||
21 | #include <zebra.h> | |
22 | ||
744d91b3 | 23 | #include "if.h" |
346cffe3 | 24 | #include "log.h" |
dfe43e25 DW |
25 | #include "prefix.h" |
26 | #include "vty.h" | |
27 | #include "plist.h" | |
744d91b3 | 28 | |
12e41d03 | 29 | #include "pimd.h" |
75a26779 | 30 | #include "pim_vty.h" |
12e41d03 DL |
31 | #include "pim_pim.h" |
32 | #include "pim_msg.h" | |
33 | #include "pim_util.h" | |
346cffe3 | 34 | #include "pim_str.h" |
7176984f | 35 | #include "pim_iface.h" |
75a26779 | 36 | #include "pim_rp.h" |
d67f268e | 37 | #include "pim_rpf.h" |
5637da05 | 38 | #include "pim_register.h" |
982bff89 | 39 | #include "pim_jp_agg.h" |
12e41d03 | 40 | |
f8e7d799 | 41 | void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type) |
12e41d03 | 42 | { |
70ce34ae | 43 | struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; |
12e41d03 | 44 | |
12e41d03 DL |
45 | /* |
46 | * Write header | |
47 | */ | |
70ce34ae DS |
48 | header->ver = PIM_PROTO_VERSION; |
49 | header->type = pim_msg_type; | |
50 | header->reserved = 0; | |
12e41d03 | 51 | |
12e41d03 | 52 | |
70ce34ae | 53 | header->checksum = 0; |
5637da05 CS |
54 | /* |
55 | * The checksum for Registers is done only on the first 8 bytes of the packet, | |
56 | * including the PIM header and the next 4 bytes, excluding the data packet portion | |
57 | */ | |
58 | if (pim_msg_type == PIM_MSG_TYPE_REGISTER) | |
70ce34ae | 59 | header->checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN); |
5637da05 | 60 | else |
70ce34ae | 61 | header->checksum = in_cksum (pim_msg, pim_msg_size); |
12e41d03 DL |
62 | } |
63 | ||
f8e7d799 | 64 | uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr) |
12e41d03 | 65 | { |
12e41d03 DL |
66 | buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ |
67 | buf[1] = '\0'; /* native encoding */ | |
68 | memcpy(buf+2, &addr, sizeof(struct in_addr)); | |
69 | ||
811ed42a | 70 | return buf + PIM_ENCODED_IPV4_UCAST_SIZE; |
12e41d03 DL |
71 | } |
72 | ||
f8e7d799 | 73 | uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr) |
12e41d03 | 74 | { |
12e41d03 DL |
75 | buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ |
76 | buf[1] = '\0'; /* native encoding */ | |
77 | buf[2] = '\0'; /* reserved */ | |
78 | buf[3] = 32; /* mask len */ | |
79 | memcpy(buf+4, &addr, sizeof(struct in_addr)); | |
80 | ||
811ed42a | 81 | return buf + PIM_ENCODED_IPV4_GROUP_SIZE; |
12e41d03 DL |
82 | } |
83 | ||
984c84f4 | 84 | uint8_t * |
f8e7d799 DS |
85 | pim_msg_addr_encode_ipv4_source(uint8_t *buf, |
86 | struct in_addr addr, uint8_t bits) | |
12e41d03 | 87 | { |
12e41d03 DL |
88 | buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ |
89 | buf[1] = '\0'; /* native encoding */ | |
984c84f4 | 90 | buf[2] = bits; |
12e41d03 DL |
91 | buf[3] = 32; /* mask len */ |
92 | memcpy(buf+4, &addr, sizeof(struct in_addr)); | |
93 | ||
811ed42a | 94 | return buf + PIM_ENCODED_IPV4_SOURCE_SIZE; |
12e41d03 | 95 | } |
346cffe3 | 96 | |
982bff89 DS |
97 | /* |
98 | * For the given 'struct pim_jp_sources' list | |
99 | * determine the size_t it would take up. | |
100 | */ | |
101 | size_t | |
102 | pim_msg_get_jp_group_size (struct list *sources) | |
103 | { | |
104 | size_t size = 0; | |
105 | ||
106 | size += sizeof (struct pim_encoded_group_ipv4); | |
107 | size += 4; // Joined sources (2) + Pruned Sources (2) | |
108 | ||
109 | size += sizeof (struct pim_encoded_source_ipv4) * sources->count; | |
110 | ||
111 | return size; | |
112 | } | |
113 | ||
114 | size_t | |
115 | pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs) | |
79bdcd99 | 116 | { |
982bff89 DS |
117 | struct listnode *node, *nnode; |
118 | struct pim_jp_sources *source; | |
79bdcd99 DS |
119 | struct in_addr stosend; |
120 | uint8_t bits; | |
982bff89 DS |
121 | size_t size = pim_msg_get_jp_group_size (sgs->sources); |
122 | uint8_t tgroups = 0; | |
79bdcd99 | 123 | |
982bff89 DS |
124 | memset (grp, 0, size); |
125 | pim_msg_addr_encode_ipv4_group ((uint8_t *)&grp->g, sgs->group); | |
79bdcd99 | 126 | |
982bff89 | 127 | for (ALL_LIST_ELEMENTS(sgs->sources, node, nnode, source)) |
79bdcd99 | 128 | { |
982bff89 DS |
129 | /* number of joined/pruned sources */ |
130 | if (source->is_join) | |
131 | grp->joins++; | |
132 | else | |
133 | grp->prunes++; | |
79bdcd99 | 134 | |
982bff89 DS |
135 | if (source->up->sg.src.s_addr == INADDR_ANY) |
136 | { | |
137 | struct pim_rpf *rpf = pim_rp_g (source->up->sg.grp); | |
138 | bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; | |
139 | stosend = rpf->rpf_addr.u.prefix4; | |
140 | } | |
141 | else | |
142 | { | |
143 | bits = PIM_ENCODE_SPARSE_BIT; | |
144 | stosend = source->up->sg.src; | |
145 | } | |
146 | ||
147 | pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[tgroups], stosend, bits); | |
148 | tgroups++; | |
149 | } | |
79bdcd99 | 150 | |
982bff89 DS |
151 | grp->joins = htons(grp->joins); |
152 | grp->prunes = htons(grp->prunes); | |
79bdcd99 DS |
153 | /* |
154 | * This is not implemented correctly at this point in time | |
155 | * Make it stop. | |
156 | */ | |
157 | #if 0 | |
158 | if (up->sg.src.s_addr == INADDR_ANY) | |
159 | { | |
160 | struct pim_upstream *child; | |
161 | struct listnode *up_node; | |
162 | int send_prune = 0; | |
163 | ||
164 | zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", | |
165 | __PRETTY_FUNCTION__, up->sg_str); | |
166 | for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) | |
167 | { | |
168 | if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) | |
169 | { | |
170 | if (!pim_rpf_is_same(&up->rpf, &child->rpf)) | |
171 | { | |
172 | send_prune = 1; | |
173 | if (PIM_DEBUG_PIM_PACKETS) | |
174 | zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", | |
175 | __PRETTY_FUNCTION__, up->sg_str, child->sg_str); | |
176 | } | |
177 | else | |
178 | if (PIM_DEBUG_PIM_PACKETS) | |
179 | zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", | |
180 | __PRETTY_FUNCTION__, up->sg_str, child->sg_str); | |
181 | } | |
182 | else if (pim_upstream_is_sg_rpt (child)) | |
183 | { | |
184 | if (pim_upstream_empty_inherited_olist (child)) | |
185 | { | |
186 | send_prune = 1; | |
187 | if (PIM_DEBUG_PIM_PACKETS) | |
188 | zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", | |
189 | __PRETTY_FUNCTION__, child->sg_str); | |
190 | } | |
191 | else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) | |
192 | { | |
193 | send_prune = 1; | |
194 | if (PIM_DEBUG_PIM_PACKETS) | |
195 | zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", | |
196 | __PRETTY_FUNCTION__, up->sg_str, child->sg_str); | |
197 | } | |
198 | else | |
199 | if (PIM_DEBUG_PIM_PACKETS) | |
200 | zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", | |
201 | __PRETTY_FUNCTION__, up->sg_str, child->sg_str); | |
202 | } | |
203 | else | |
204 | if (PIM_DEBUG_PIM_PACKETS) | |
205 | zlog_debug ("%s: SPT bit is not set for (%s)", | |
206 | __PRETTY_FUNCTION__, child->sg_str); | |
207 | if (send_prune) | |
208 | { | |
209 | pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain, | |
210 | child->sg.src, | |
211 | PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT); | |
212 | remain = pim_msg_curr - pim_msg; | |
213 | *prunes = htons(ntohs(*prunes) + 1); | |
214 | send_prune = 0; | |
215 | } | |
216 | } | |
217 | } | |
218 | #endif | |
219 | ||
982bff89 | 220 | return size; |
346cffe3 | 221 | } |