wccp.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 80 WCCP Support */
10
11#include "squid.h"
12
13#if USE_WCCP
14#include "comm.h"
15#include "comm/Connection.h"
16#include "comm/Loops.h"
17#include "event.h"
18#include "fatal.h"
19#include "SquidConfig.h"
20#include "wccp.h"
21
22#define WCCP_PORT 2048
23#define WCCP_REVISION 0
24#define WCCP_ACTIVE_CACHES 32
25#define WCCP_HASH_SIZE 32
26#define WCCP_BUCKETS 256
27#define WCCP_CACHE_LEN 4
28
29#define WCCP_HERE_I_AM 7
30#define WCCP_I_SEE_YOU 8
31#define WCCP_ASSIGN_BUCKET 9
32
34 int type;
39 int id;
40};
41
43 struct in_addr ip_addr; // WCCP on-the-wire in 32-bit IPv4-only.
47};
48
50 int32_t type;
51 int32_t version;
52 int32_t change;
53 int32_t id;
54 int32_t number;
55
57};
58
60 int type;
61 int id;
62 int number;
63};
64
65static int theWccpConnection = -1;
66
68
70static int last_change;
71static int last_id;
73static unsigned int number_caches;
74
76
78static int wccpLowestIP(void);
80static void wccpAssignBuckets(void);
81
82/*
83 * The functions used during startup:
84 * wccpInit
85 * wccpConnectionOpen
86 * wccpConnectionShutdown
87 * wccpConnectionClose
88 */
89
90void
92{
93 debugs(80, 5, "wccpInit: Called");
94 memset(&wccp_here_i_am, '\0', sizeof(wccp_here_i_am));
98 last_change = 0;
99 last_id = 0;
101 number_caches = 0;
102
104 if (!eventFind(wccpHereIam, nullptr))
105 eventAdd("wccpHereIam", wccpHereIam, nullptr, 5.0, 1);
106}
107
108void
110{
111 debugs(80, 5, "wccpConnectionOpen: Called");
112
113 if (Config.Wccp.router.isAnyAddr()) {
114 debugs(80, 2, "WCCPv1 disabled.");
115 return;
116 }
117
118 if ( !Config.Wccp.router.setIPv4() ) {
119 debugs(80, DBG_CRITICAL, "WCCPv1 Disabled. Router " << Config.Wccp.router << " is not an IPv4 address.");
120 return;
121 }
122
123 if ( !Config.Wccp.address.setIPv4() ) {
124 debugs(80, DBG_CRITICAL, "WCCPv1 Disabled. Local address " << Config.Wccp.address << " is not an IPv4 address.");
125 return;
126 }
127
130
132 IPPROTO_UDP,
135 "WCCP Socket");
136
137 if (theWccpConnection < 0)
138 fatal("Cannot open WCCP Port");
139
141
142 debugs(80, DBG_IMPORTANT, "Accepting WCCPv1 messages on " << Config.Wccp.address << ", FD " << theWccpConnection << ".");
143
144 // Sadly WCCP only does IPv4
145
146 struct sockaddr_in router;
148 if (connect(theWccpConnection, (struct sockaddr*)&router, sizeof(router)))
149 fatal("Unable to connect WCCP out socket");
150
151 struct sockaddr_in local;
152 memset(&local, '\0', sizeof(local));
153 socklen_t slen = sizeof(local);
154 if (getsockname(theWccpConnection, (struct sockaddr*)&local, &slen))
155 fatal("Unable to getsockname on WCCP out socket");
156
157 local_ip = local;
158}
159
160void
162{
163 if (theWccpConnection > -1) {
164 debugs(80, DBG_IMPORTANT, "FD " << theWccpConnection << " Closing WCCPv1 socket");
167 }
168}
169
170/*
171 * Functions for handling the requests.
172 */
173
174/*
175 * Accept the UDP packet
176 */
177static void
178wccpHandleUdp(int sock, void *)
179{
180 Ip::Address from;
181 int len;
182
183 debugs(80, 6, "wccpHandleUdp: Called.");
184
186
187 memset(&wccp_i_see_you, '\0', sizeof(wccp_i_see_you));
188
189 len = comm_udp_recvfrom(sock,
190 (void *) &wccp_i_see_you,
191 sizeof(wccp_i_see_you),
192 0,
193 from);
194 debugs(80, 3, "wccpHandleUdp: " << len << " bytes WCCP pkt from " << from <<
195 ": type=" <<
196 (unsigned) ntohl(wccp_i_see_you.type) << ", version=" <<
197 (unsigned) ntohl(wccp_i_see_you.version) << ", change=" <<
198 (unsigned) ntohl(wccp_i_see_you.change) << ", id=" <<
199 (unsigned) ntohl(wccp_i_see_you.id) << ", number=" <<
200 (unsigned) ntohl(wccp_i_see_you.number));
201
202 if (len < 0)
203 return;
204
205 if (from != Config.Wccp.router)
206 return;
207
208 if ((unsigned) ntohl(wccp_i_see_you.version) != (unsigned) Config.Wccp.version)
209 return;
210
211 if (ntohl(wccp_i_see_you.type) != WCCP_I_SEE_YOU)
212 return;
213
215 debugs(80, DBG_IMPORTANT, "Ignoring WCCP_I_SEE_YOU from " <<
216 from << " with number of caches set to " <<
217 (int) ntohl(wccp_i_see_you.number));
218
219 return;
220 }
221
223
224 if ((0 == last_change) && (number_caches == (unsigned) ntohl(wccp_i_see_you.number))) {
226 /*
227 * After a WCCP_ASSIGN_BUCKET message, the router should
228 * update the change value. If not, maybe the route didn't
229 * receive our WCCP_ASSIGN_BUCKET message, so send it again.
230 *
231 * Don't update change here. Instead, fall through to
232 * the next block to call wccpAssignBuckets() again.
233 */
234 (void) 0;
235 } else {
237 return;
238 }
239 }
240
243
247 }
248 }
249}
250
251static int
253{
254 unsigned int loop;
255 int found = 0;
256
257 /*
258 * We sanity checked wccp_i_see_you.number back in wccpHandleUdp()
259 */
260
261 for (loop = 0; loop < (unsigned) ntohl(wccp_i_see_you.number); ++loop) {
263
265 return 0;
266
268 found = 1;
269 }
270
271 return found;
272}
273
274static void
276{
277 debugs(80, 6, "wccpHereIam: Called");
278
280 double interval = 10.0; // TODO: make this configurable, possibly negotiate with the router.
281 ssize_t sent = comm_udp_send(theWccpConnection, &wccp_here_i_am, sizeof(wccp_here_i_am), 0);
282
283 // if we failed to send the whole lot, try again at a shorter interval (20%)
284 if (sent != sizeof(wccp_here_i_am)) {
285 int xerrno = errno;
286 debugs(80, 2, "ERROR: failed to send WCCP HERE_I_AM packet: " << xstrerr(xerrno));
287 interval = 2.0;
288 }
289
290 if (!eventFind(wccpHereIam, nullptr))
291 eventAdd("wccpHereIam", wccpHereIam, nullptr, interval, 1);
292}
293
294static void
296{
297
298 struct wccp_assign_bucket_t *wccp_assign_bucket;
299 int wab_len;
300 char *buckets;
301 int buckets_per_cache;
302 unsigned int loop;
303 int bucket = 0;
304 int *caches;
305 int cache_len;
306 char *buf;
307
308 debugs(80, 6, "wccpAssignBuckets: Called");
310
313
314 wab_len = sizeof(struct wccp_assign_bucket_t);
315
316 cache_len = WCCP_CACHE_LEN * number_caches;
317
318 buf = (char *)xmalloc(wab_len +
320 cache_len);
321
322 wccp_assign_bucket = (struct wccp_assign_bucket_t *) buf;
323
324 caches = (int *) (buf + wab_len);
325
326 buckets = buf + wab_len + cache_len;
327
328 memset(wccp_assign_bucket, '\0', sizeof(*wccp_assign_bucket));
329
330 memset(buckets, 0xFF, WCCP_BUCKETS);
331
332 buckets_per_cache = WCCP_BUCKETS / number_caches;
333
334 for (loop = 0; loop < number_caches; ++loop) {
335 int i;
336 memcpy(&caches[loop],
338 sizeof(*caches));
339
340 for (i = 0; i < buckets_per_cache; ++i) {
341 assert(bucket < WCCP_BUCKETS);
342 buckets[bucket] = loop;
343 ++bucket;
344 }
345 }
346
347 while (bucket < WCCP_BUCKETS) {
348 buckets[bucket] = number_caches - 1;
349 ++bucket;
350 }
351
352 wccp_assign_bucket->type = htonl(WCCP_ASSIGN_BUCKET);
353 wccp_assign_bucket->id = wccp_i_see_you.id;
354 wccp_assign_bucket->number = wccp_i_see_you.number;
355
357 buf,
358 wab_len + WCCP_BUCKETS + cache_len,
359 0);
360 last_change = 0;
361 xfree(buf);
362}
363
364#endif /* USE_WCCP */
365
#define COMM_NONBLOCKING
Definition: Connection.h:46
class SquidConfig Config
Definition: SquidConfig.cc:12
#define assert(EX)
Definition: assert.h:19
bool setIPv4()
Definition: Address.cc:224
void getSockAddr(struct sockaddr_storage &addr, const int family) const
Definition: Address.cc:924
bool isAnyAddr() const
Definition: Address.cc:170
unsigned short port() const
Definition: Address.cc:778
Ip::Address address
Definition: SquidConfig.h:161
struct SquidConfig::@101 Wccp
Ip::Address router
Definition: SquidConfig.h:160
void PF(int, void *)
Definition: forward.h:18
void comm_open_listener(int sock_type, int proto, Comm::ConnectionPointer &conn, const char *note)
Definition: comm.cc:255
ssize_t comm_udp_send(int s, const void *buf, size_t len, int flags)
Definition: comm.cc:144
int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, Ip::Address &from)
Definition: comm.cc:124
#define comm_close(x)
Definition: comm.h:27
#define DBG_IMPORTANT
Definition: Stream.h:41
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
#define DBG_CRITICAL
Definition: Stream.h:40
#define COMM_SELECT_READ
Definition: defines.h:24
int eventFind(EVH *func, void *arg)
Definition: event.cc:145
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:107
void EVH(void *)
Definition: event.h:18
void fatal(const char *message)
Definition: fatal.cc:28
void SetSelect(int, unsigned int, PF *, void *, time_t)
Mark an FD to be watched for its IO status.
Definition: ModDevPoll.cc:223
#define xfree
#define xmalloc
static struct tok * buckets[HASHSIZE]
Definition: parse.c:219
Definition: wccp.cc:42
int revision
Definition: wccp.cc:44
struct in_addr ip_addr
Definition: wccp.cc:43
char hash[WCCP_HASH_SIZE]
Definition: wccp.cc:45
int reserved
Definition: wccp.cc:46
int revision
Definition: wccp.cc:36
char hash[WCCP_HASH_SIZE]
Definition: wccp.cc:37
int reserved
Definition: wccp.cc:38
int32_t change
Definition: wccp.cc:52
int32_t number
Definition: wccp.cc:54
int32_t version
Definition: wccp.cc:51
int32_t id
Definition: wccp.cc:53
struct wccp_cache_entry_t wccp_cache_entry[WCCP_ACTIVE_CACHES]
Definition: wccp.cc:56
int32_t type
Definition: wccp.cc:50
int socklen_t
Definition: types.h:158
void wccpConnectionClose(void)
Definition: wccp.cc:161
#define WCCP_I_SEE_YOU
Definition: wccp.cc:30
static PF wccpHandleUdp
Definition: wccp.cc:77
static Ip::Address local_ip
Definition: wccp.cc:75
#define WCCP_ACTIVE_CACHES
Definition: wccp.cc:24
static int last_assign_buckets_change
Definition: wccp.cc:72
#define WCCP_REVISION
Definition: wccp.cc:23
static unsigned int number_caches
Definition: wccp.cc:73
static int last_change
Definition: wccp.cc:70
#define WCCP_CACHE_LEN
Definition: wccp.cc:27
#define WCCP_ASSIGN_BUCKET
Definition: wccp.cc:31
static int wccpLowestIP(void)
Definition: wccp.cc:252
#define WCCP_BUCKETS
Definition: wccp.cc:26
#define WCCP_PORT
Definition: wccp.cc:22
static int theWccpConnection
Definition: wccp.cc:65
static void wccpAssignBuckets(void)
Definition: wccp.cc:295
#define WCCP_HASH_SIZE
Definition: wccp.cc:25
void wccpConnectionOpen(void)
Definition: wccp.cc:109
static struct wccp_i_see_you_t wccp_i_see_you
Definition: wccp.cc:69
static EVH wccpHereIam
Definition: wccp.cc:79
static struct wccp_here_i_am_t wccp_here_i_am
Definition: wccp.cc:67
void wccpInit(void)
Definition: wccp.cc:91
#define WCCP_HERE_I_AM
Definition: wccp.cc:29
static int last_id
Definition: wccp.cc:71
const char * xstrerr(int error)
Definition: xstrerror.cc:83

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors