Revision f4a60a9b proto/pipe/pipe.c

View differences:

proto/pipe/pipe.c
46 46
static void
47 47
pipe_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, ea_list *attrs)
48 48
{
49
  struct pipe_proto *p = (struct pipe_proto *) P;
50
  struct announce_hook *ah = (src_table == P->table) ? p->peer_ahook : P->main_ahook;
51
  rtable *dst_table = ah->table;
49
  struct pipe_proto *p = (void *) P;
50
  struct channel *dst = (src_table == p->pri->table) ? p->sec : p->pri;
52 51
  struct rte_src *src;
53 52

  
54 53
  net *nn;
......
58 57
  if (!new && !old)
59 58
    return;
60 59

  
61
  if (dst_table->pipe_busy)
60
  if (dst->table->pipe_busy)
62 61
    {
63 62
      log(L_ERR "Pipe loop detected when sending %N to table %s",
64
	  n->n.addr, dst_table->name);
63
	  n->n.addr, dst->table->name);
65 64
      return;
66 65
    }
67 66

  
68
  nn = net_get(dst_table, n->n.addr);
67
  nn = net_get(dst->table, n->n.addr);
69 68
  if (new)
70 69
    {
71 70
      memcpy(&a, new->attrs, sizeof(rta));
72 71

  
73
      if (p->mode == PIPE_OPAQUE)
74
	{
75
	  a.src = P->main_source;
76
	  a.source = RTS_PIPE;
77
	}
78

  
79 72
      a.aflags = 0;
80 73
      a.eattrs = attrs;
81 74
      a.hostentry = NULL;
......
83 76
      e->net = nn;
84 77
      e->pflags = 0;
85 78

  
86
      if (p->mode == PIPE_TRANSPARENT)
87
	{
88
	  /* Copy protocol specific embedded attributes. */
89
	  memcpy(&(e->u), &(new->u), sizeof(e->u));
90
	  e->pref = new->pref;
91
	  e->pflags = new->pflags;
92
	}
79
      /* Copy protocol specific embedded attributes. */
80
      memcpy(&(e->u), &(new->u), sizeof(e->u));
81
      e->pref = new->pref;
82
      e->pflags = new->pflags;
93 83

  
94 84
      src = a.src;
95 85
    }
......
100 90
    }
101 91

  
102 92
  src_table->pipe_busy = 1;
103
  rte_update2(ah, nn, e, src);
93
  rte_update2(dst, nn, e, src);
104 94
  src_table->pipe_busy = 0;
105 95
}
106 96

  
......
111 101

  
112 102
  if (pp == P)
113 103
    return -1;	/* Avoid local loops automatically */
104

  
114 105
  return 0;
115 106
}
116 107

  
117
static int
118
pipe_reload_routes(struct proto *P)
108
static void
109
pipe_reload_routes(struct channel *C)
119 110
{
120
  struct pipe_proto *p = (struct pipe_proto *) P;
121

  
122
  /*
123
   * Because the pipe protocol feeds routes from both routing tables
124
   * together, both directions are reloaded during refeed and 'reload
125
   * out' command works like 'reload' command. For symmetry, we also
126
   * request refeed when 'reload in' command is used.
127
   */
128
  proto_request_feeding(P);
111
  struct pipe_proto *p = (void *) C->proto;
129 112

  
130
  proto_reset_limit(P->main_ahook->in_limit);
131
  proto_reset_limit(p->peer_ahook->in_limit);
132

  
133
  return 1;
113
  /* Route reload on one channel is just refeed on the other */
114
  channel_request_feeding((C == p->pri) ? p->sec : p->pri);
134 115
}
135 116

  
136
static struct proto *
137
pipe_init(struct proto_config *C)
138
{
139
  struct pipe_config *c = (struct pipe_config *) C;
140
  struct proto *P = proto_new(C, sizeof(struct pipe_proto));
141
  struct pipe_proto *p = (struct pipe_proto *) P;
142 117

  
143
  p->mode = c->mode;
144
  p->peer_table = c->peer->table;
145
  P->accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY;
146
  P->rt_notify = pipe_rt_notify;
147
  P->import_control = pipe_import_control;
148
  P->reload_routes = pipe_reload_routes;
149

  
150
  return P;
151
}
152

  
153
static int
154
pipe_start(struct proto *P)
118
static void
119
pipe_postconfig(struct proto_config *CF)
155 120
{
156
  struct pipe_config *cf = (struct pipe_config *) P->cf;
157
  struct pipe_proto *p = (struct pipe_proto *) P;
121
  struct pipe_config *cf = (void *) CF;
122
  struct channel_config *cc = proto_cf_main_channel(CF);
158 123

  
159
  /* Lock both tables, unlock is handled in pipe_cleanup() */
160
  rt_lock_table(P->table);
161
  rt_lock_table(p->peer_table);
124
  if (!cc->table)
125
    cf_error("Primary routing table not specified");
162 126

  
163
  /* Going directly to PS_UP - prepare for feeding,
164
     connect the protocol to both routing tables */
127
  if (!cf->peer)
128
    cf_error("Secondary routing table not specified");
165 129

  
166
  P->main_ahook = proto_add_announce_hook(P, P->table, &P->stats);
167
  P->main_ahook->out_filter = cf->c.out_filter;
168
  P->main_ahook->in_limit = cf->c.in_limit;
169
  proto_reset_limit(P->main_ahook->in_limit);
130
  if (cc->table == cf->peer)
131
    cf_error("Primary table and peer table must be different");
170 132

  
171
  p->peer_ahook = proto_add_announce_hook(P, p->peer_table, &p->peer_stats);
172
  p->peer_ahook->out_filter = cf->c.in_filter;
173
  p->peer_ahook->in_limit = cf->c.out_limit;
174
  proto_reset_limit(p->peer_ahook->in_limit);
133
  if (cc->table->addr_type != cf->peer->addr_type)
134
    cf_error("Primary table and peer table must have the same type");
175 135

  
176
  if (p->mode == PIPE_OPAQUE)
177
    {
178
      P->main_source = rt_get_source(P, 0);
179
      rt_lock_source(P->main_source);
180
    }
136
  if (cc->rx_limit.action)
137
    cf_error("Pipe protocol does not support receive limits");
181 138

  
182
  return PS_UP;
139
  if (cc->in_keep_filtered)
140
    cf_error("Pipe protocol prohibits keeping filtered routes");
183 141
}
184 142

  
185
static void
186
pipe_cleanup(struct proto *P)
143
static int
144
pipe_configure_channels(struct pipe_proto *p, struct pipe_config *cf)
187 145
{
188
  struct pipe_proto *p = (struct pipe_proto *) P;
189

  
190
  bzero(&P->stats, sizeof(struct proto_stats));
191
  bzero(&p->peer_stats, sizeof(struct proto_stats));
192

  
193
  P->main_ahook = NULL;
194
  p->peer_ahook = NULL;
195

  
196
  if (p->mode == PIPE_OPAQUE)
197
    rt_unlock_source(P->main_source);
198
  P->main_source = NULL;
199

  
200
  rt_unlock_table(P->table);
201
  rt_unlock_table(p->peer_table);
146
  struct channel_config *cc = proto_cf_main_channel(&cf->c);
147

  
148
  struct channel_config pri_cf = {
149
    .name = "pri",
150
    .channel = cc->channel,
151
    .table = cc->table,
152
    .out_filter = cc->out_filter,
153
    .in_limit = cc->in_limit,
154
    .ra_mode = RA_ANY
155
  };
156

  
157
  struct channel_config sec_cf = {
158
    .name = "sec",
159
    .channel = cc->channel,
160
    .table = cf->peer,
161
    .out_filter = cc->in_filter,
162
    .in_limit = cc->out_limit,
163
    .ra_mode = RA_ANY
164
  };
165

  
166
  return
167
    proto_configure_channel(&p->p, &p->pri, &pri_cf) &&
168
    proto_configure_channel(&p->p, &p->sec, &sec_cf);
202 169
}
203 170

  
204
static void
205
pipe_postconfig(struct proto_config *C)
171
static struct proto *
172
pipe_init(struct proto_config *CF)
206 173
{
207
  struct pipe_config *c = (struct pipe_config *) C;
174
  struct proto *P = proto_new(CF);
175
  struct pipe_proto *p = (void *) P;
176
  struct pipe_config *cf = (void *) CF;
208 177

  
209
  if (!c->peer)
210
    cf_error("Name of peer routing table not specified");
211
  if (c->peer == C->table)
212
    cf_error("Primary table and peer table must be different");
178
  P->rt_notify = pipe_rt_notify;
179
  P->import_control = pipe_import_control;
180
  P->reload_routes = pipe_reload_routes;
213 181

  
214
  if (C->in_keep_filtered)
215
    cf_error("Pipe protocol prohibits keeping filtered routes");
216
  if (C->rx_limit)
217
    cf_error("Pipe protocol does not support receive limits");
218
}
182
  pipe_configure_channels(p, cf);
219 183

  
220
extern int proto_reconfig_type;
184
  return P;
185
}
221 186

  
222 187
static int
223
pipe_reconfigure(struct proto *P, struct proto_config *new)
188
pipe_reconfigure(struct proto *P, struct proto_config *CF)
224 189
{
225
  struct pipe_proto *p = (struct pipe_proto *)P;
226
  struct proto_config *old = P->cf;
227
  struct pipe_config *oc = (struct pipe_config *) old;
228
  struct pipe_config *nc = (struct pipe_config *) new;
229

  
230
  if ((oc->peer->table != nc->peer->table) || (oc->mode != nc->mode))
231
    return 0;
232

  
233
  /* Update output filters in ahooks */
234
  if (P->main_ahook)
235
    {
236
      P->main_ahook->out_filter = new->out_filter;
237
      P->main_ahook->in_limit = new->in_limit;
238
      proto_verify_limits(P->main_ahook);
239
    }
240

  
241
  if (p->peer_ahook)
242
    {
243
      p->peer_ahook->out_filter = new->in_filter;
244
      p->peer_ahook->in_limit = new->out_limit;
245
      proto_verify_limits(p->peer_ahook);
246
    }
247

  
248
  if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT))
249
    return 1;
250

  
251
  if ((new->preference != old->preference)
252
      || ! filter_same(new->in_filter, old->in_filter)
253
      || ! filter_same(new->out_filter, old->out_filter))
254
    proto_request_feeding(P);
190
  struct pipe_proto *p = (void *) P;
191
  struct pipe_config *cf = (void *) CF;
255 192

  
256
  return 1;
193
  return pipe_configure_channels(p, cf);
257 194
}
258 195

  
259 196
static void
260 197
pipe_copy_config(struct proto_config *dest, struct proto_config *src)
261 198
{
262 199
  /* Just a shallow copy, not many items here */
263
  proto_copy_rest(dest, src, sizeof(struct pipe_config));
264 200
}
265 201

  
266 202
static void
267 203
pipe_get_status(struct proto *P, byte *buf)
268 204
{
269
  struct pipe_proto *p = (struct pipe_proto *) P;
205
  struct pipe_proto *p = (void *) P;
270 206

  
271
  bsprintf(buf, "%c> %s", (p->mode == PIPE_OPAQUE) ? '-' : '=', p->peer_table->name);
207
  bsprintf(buf, "%s <=> %s", p->pri->table->name, p->sec->table->name);
272 208
}
273 209

  
274 210
static void
275 211
pipe_show_stats(struct pipe_proto *p)
276 212
{
277
  struct proto_stats *s1 = &p->p.stats;
278
  struct proto_stats *s2 = &p->peer_stats;
213
  struct proto_stats *s1 = &p->pri->stats;
214
  struct proto_stats *s2 = &p->sec->stats;
279 215

  
280 216
  /*
281 217
   * Pipe stats (as anything related to pipes) are a bit tricky. There
......
318 254
static void
319 255
pipe_show_proto_info(struct proto *P)
320 256
{
321
  struct pipe_proto *p = (struct pipe_proto *) P;
322
  struct pipe_config *cf = (struct pipe_config *) P->cf;
257
  struct pipe_proto *p = (void *) P;
323 258

  
324
  // cli_msg(-1006, "  Table:          %s", P->table->name);
325
  // cli_msg(-1006, "  Peer table:     %s", p->peer_table->name);
326
  cli_msg(-1006, "  Preference:     %d", P->preference);
327
  cli_msg(-1006, "  Input filter:   %s", filter_name(cf->c.in_filter));
328
  cli_msg(-1006, "  Output filter:  %s", filter_name(cf->c.out_filter));
259
  cli_msg(-1006, "  Channel %s", "main");
260
  cli_msg(-1006, "    Table:          %s", p->pri->table->name);
261
  cli_msg(-1006, "    Peer table:     %s", p->sec->table->name);
262
  cli_msg(-1006, "    Import filter:  %s", filter_name(p->sec->out_filter));
263
  cli_msg(-1006, "    Export filter:  %s", filter_name(p->pri->out_filter));
329 264

  
330
  proto_show_limit(cf->c.in_limit, "Import limit:");
331
  proto_show_limit(cf->c.out_limit, "Export limit:");
265
  channel_show_limit(&p->pri->in_limit, "Import limit:");
266
  channel_show_limit(&p->sec->in_limit, "Export limit:");
332 267

  
333 268
  if (P->proto_state != PS_DOWN)
334 269
    pipe_show_stats(p);
......
338 273
struct protocol proto_pipe = {
339 274
  .name =		"Pipe",
340 275
  .template =		"pipe%d",
341
  .multitable =		1,
342
  .preference =		DEF_PREF_PIPE,
276
  .proto_size =		sizeof(struct pipe_proto),
343 277
  .config_size =	sizeof(struct pipe_config),
344 278
  .postconfig =		pipe_postconfig,
345 279
  .init =		pipe_init,
346
  .start =		pipe_start,
347
  .cleanup =		pipe_cleanup,
348 280
  .reconfigure =	pipe_reconfigure,
349 281
  .copy_config = 	pipe_copy_config,
350 282
  .get_status = 	pipe_get_status,

Also available in: Unified diff