~ubuntu-branches/ubuntu/wily/marionnet/wily

« back to all changes in this revision

Viewing changes to router.ml

  • Committer: Package Import Robot
  • Author(s): Lucas Nussbaum
  • Date: 2013-03-29 15:57:12 UTC
  • Revision ID: package-import@ubuntu.com-20130329155712-o0b9b96w8av68ktq
Tags: upstream-0.90.6+bzr407
ImportĀ upstreamĀ versionĀ 0.90.6+bzr407

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(* This file is part of Marionnet, a virtual network laboratory
 
2
   Copyright (C) 2009, 2010  Jean-Vincent Loddo
 
3
   Copyright (C) 2009, 2010  UniversitĆ© Paris 13
 
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,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
   GNU 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.  If not, see <http://www.gnu.org/licenses/>. *)
 
17
 
 
18
open Gettext;;
 
19
 
 
20
(** Gui-related stuff for the user-level component "router". *)
 
21
 
 
22
(* The module containing the add/update dialog is defined later,
 
23
   using the syntax extension "where" *)
 
24
#load "where_p4.cmo"
 
25
;;
 
26
 
 
27
(* Router related constants: *)
 
28
(* TODO: make it configurable! *)
 
29
module Const = struct
 
30
 let port_no_default = 4
 
31
 let port_no_min = 4
 
32
 let port_no_max = 16
 
33
 
 
34
 let port_0_ip_config_default = Initialization.router_port0_default_ipv4_config
 
35
 let memory_default = 48
 
36
end
 
37
 
 
38
 
 
39
(* The type of data returned by the dialog: *)
 
40
module Data = struct
 
41
type t = {
 
42
  name               : string;
 
43
  label              : string;
 
44
  port_0_ip_config   : Ipv4.config;
 
45
  port_no            : int;
 
46
  distribution       : string;          (* epithet *)
 
47
  variant            : string option;
 
48
  kernel             : string;          (* epithet *)
 
49
  show_unix_terminal : bool;
 
50
  old_name           : string;
 
51
  }
 
52
 
 
53
let to_string t = "<obj>" (* TODO? *)
 
54
end (* Data *)
 
55
 
 
56
module Make_menus (Params : sig
 
57
  val st      : State.globalState
 
58
  val packing : [ `toolbar of GButton.toolbar | `menu_parent of Menu_factory.menu_parent ]
 
59
 end) = struct
 
60
 
 
61
  open Params
 
62
 
 
63
  module Toolbar_entry = struct
 
64
   let imagefile = "ico.router.palette.png"
 
65
   let tooltip   = (s_ "Router")
 
66
   let packing   = Params.packing
 
67
  end
 
68
 
 
69
  module Add = struct
 
70
    include Data
 
71
 
 
72
    let key = Some GdkKeysyms._R
 
73
 
 
74
    let ok_callback t = Gui_bricks.Ok_callback.check_name t.name t.old_name st#network#name_exists t
 
75
 
 
76
    let dialog () =
 
77
      let name = st#network#suggestedName "R" in
 
78
      Dialog_add_or_update.make
 
79
        ~title:(s_ "Add router") ~name ~ok_callback ()
 
80
 
 
81
    let reaction {
 
82
         name = name;
 
83
         label = label;
 
84
         port_0_ip_config = port_0_ip_config;
 
85
         port_no = port_no;
 
86
         distribution = distribution;
 
87
         variant = variant;
 
88
         kernel = kernel;
 
89
         show_unix_terminal = show_unix_terminal;
 
90
         old_name = _ ;
 
91
         }
 
92
      =
 
93
      let action () = ignore (
 
94
        new User_level_router.router (* defined later with WHERE *)
 
95
          ~network:st#network
 
96
          ~name
 
97
          ~label
 
98
          ~port_0_ip_config
 
99
          ~epithet:distribution
 
100
          ?variant:variant
 
101
          ~kernel
 
102
          ~port_no
 
103
          ~show_unix_terminal
 
104
          ())
 
105
      in
 
106
      st#network_change action ();
 
107
 
 
108
  end (* Add *)
 
109
 
 
110
  module Properties = struct
 
111
    include Data
 
112
    let dynlist () = st#network#get_nodes_that_can_startup ~devkind:`Router ()
 
113
 
 
114
    let dialog name () =
 
115
     let r = (st#network#get_node_by_name name) in
 
116
     let r = ((Obj.magic r):> User_level_router.router) in
 
117
     let title = (s_ "Modify router")^" "^name in
 
118
     let label = r#get_label in
 
119
     let distribution = r#get_epithet in
 
120
     let variant = r#get_variant in
 
121
     let kernel = r#get_kernel in
 
122
     let show_unix_terminal = r#get_show_unix_terminal in
 
123
     let port_no = r#get_port_no in
 
124
     let port_0_ip_config = r#get_port_0_ip_config in
 
125
     (* The user cannot remove receptacles used by a cable. *)
 
126
     let port_no_min = st#network#port_no_lower_of (r :> User_level.node)
 
127
     in
 
128
     Dialog_add_or_update.make
 
129
       ~title ~name ~label ~distribution ?variant ~show_unix_terminal
 
130
       ~port_no ~port_no_min
 
131
       ~port_0_ip_config
 
132
       ~kernel
 
133
       ~updating:() (* the user cannot change the distrib & variant *)
 
134
       ~ok_callback:Add.ok_callback  ()
 
135
 
 
136
    let reaction {
 
137
         name = name;
 
138
         label = label;
 
139
         port_0_ip_config = port_0_ip_config;
 
140
         port_no = port_no;
 
141
         kernel = kernel;
 
142
         show_unix_terminal = show_unix_terminal;
 
143
         old_name = old_name;
 
144
         }
 
145
      =
 
146
      let d = (st#network#get_node_by_name old_name) in
 
147
      let r = ((Obj.magic d):> User_level_router.router) in
 
148
      let action () =
 
149
        r#update_router_with
 
150
          ~name ~label ~port_0_ip_config ~port_no ~kernel ~show_unix_terminal
 
151
      in
 
152
      st#network_change action ();
 
153
 
 
154
  end (* Properties *)
 
155
 
 
156
  module Remove = struct
 
157
    type t = string (* just the name *)
 
158
    let to_string = (Printf.sprintf "name = %s\n")
 
159
 
 
160
    let dynlist = Properties.dynlist
 
161
 
 
162
    let dialog name () =
 
163
      Gui_bricks.Dialog.yes_or_cancel_question
 
164
        ~title:(s_ "Remove")
 
165
        ~markup:(Printf.sprintf (f_ "Are you sure that you want to remove %s\nand all the cables connected to this %s?") name (s_ "router"))
 
166
        ~context:name
 
167
        ()
 
168
 
 
169
    let reaction name =
 
170
      let d = (st#network#get_node_by_name name) in
 
171
      let r = ((Obj.magic d):> User_level_router.router) in
 
172
      let action () = r#destroy in
 
173
      st#network_change action ();
 
174
 
 
175
  end
 
176
 
 
177
  module Startup = struct
 
178
    type t = string (* just the name *)
 
179
    let to_string = (Printf.sprintf "name = %s\n")
 
180
    let dynlist    = Properties.dynlist
 
181
    let dialog     = Menu_factory.no_dialog_but_simply_return_name
 
182
    let reaction name = (st#network#get_node_by_name name)#startup
 
183
 
 
184
  end
 
185
 
 
186
  module Stop = struct
 
187
    type t = string (* just the name *)
 
188
    let to_string = (Printf.sprintf "name = %s\n")
 
189
    let dynlist () = st#network#get_nodes_that_can_gracefully_shutdown ~devkind:`Router ()
 
190
    let dialog = Menu_factory.no_dialog_but_simply_return_name
 
191
    let reaction name = (st#network#get_node_by_name name)#gracefully_shutdown
 
192
 
 
193
  end
 
194
 
 
195
  module Suspend = struct
 
196
    type t = string (* just the name *)
 
197
    let to_string = (Printf.sprintf "name = %s\n")
 
198
    let dynlist () = st#network#get_nodes_that_can_suspend ~devkind:`Router ()
 
199
    let dialog = Menu_factory.no_dialog_but_simply_return_name
 
200
    let reaction name = (st#network#get_node_by_name name)#suspend
 
201
 
 
202
  end
 
203
 
 
204
  module Resume = struct
 
205
    type t = string (* just the name *)
 
206
 
 
207
    let to_string = (Printf.sprintf "name = %s\n")
 
208
    let dynlist () = st#network#get_nodes_that_can_resume ~devkind:`Router ()
 
209
    let dialog = Menu_factory.no_dialog_but_simply_return_name
 
210
    let reaction name = (st#network#get_node_by_name name)#resume
 
211
 
 
212
  end
 
213
 
 
214
 module Create_entries =
 
215
  Gui_toolbar_COMPONENTS_layouts.Layout_for_network_node (Params) (Toolbar_entry) (Add) (Properties) (Remove) (Startup) (Stop) (Suspend) (Resume)
 
216
 
 
217
 (* Subscribe this kind of component to the network club: *)
 
218
 st#network#subscribe_a_try_to_add_procedure Eval_forest_child.try_to_add_router;
 
219
 
 
220
end
 
221
 
 
222
(*-----*)
 
223
  WHERE
 
224
(*-----*)
 
225
 
 
226
module Dialog_add_or_update = struct
 
227
 
 
228
(* This function may be useful for testing the widget creation without
 
229
   recompiling the whole project. *)
 
230
let make
 
231
 ?(title="Add a router")
 
232
 ?(name="")
 
233
 ?label
 
234
 ?(port_0_ip_config=Const.port_0_ip_config_default)
 
235
 ?(port_no=Const.port_no_default)
 
236
 ?(port_no_min=Const.port_no_min)
 
237
 ?(port_no_max=Const.port_no_max)
 
238
 ?distribution
 
239
 ?variant
 
240
 ?kernel
 
241
 ?(updating:unit option)
 
242
 ?(show_unix_terminal=false)
 
243
 ?(help_callback=help_callback) (* defined backward with "WHERE" *)
 
244
 ?(ok_callback=(fun data -> Some data))
 
245
 ?(dialog_image_file=Initialization.Path.images^"ico.router.dialog.png")
 
246
 () :'result option =
 
247
  let old_name = name in
 
248
  let ((b1,b2,b3,b4),b5) = port_0_ip_config  in
 
249
  let vm_installations =  Disk.get_router_installations () in
 
250
  let (w,_,name,label) =
 
251
    Gui_bricks.Dialog_add_or_update.make_window_image_name_and_label
 
252
      ~title
 
253
      ~image_file:dialog_image_file
 
254
      ~image_tooltip:(s_ "Router")
 
255
      ~name
 
256
      ~name_tooltip:(s_ "Router name. This name must be unique in the virtual network. Suggested: R1, R2, ...")
 
257
      ?label
 
258
      ()
 
259
  in
 
260
  let ((s1,s2,s3,s4,s5), port_no, distribution_variant_kernel, show_unix_terminal) =
 
261
    let vbox = GPack.vbox ~homogeneous:false ~border_width:20 ~spacing:10 ~packing:w#vbox#add () in
 
262
    let form =
 
263
      Gui_bricks.make_form_with_labels
 
264
        ~packing:vbox#add
 
265
        [(s_ "Ports number");
 
266
         (s_ "Port 0 address");
 
267
         (s_ "Distribution");
 
268
         (s_ "Variant");
 
269
         (s_ "Kernel");
 
270
         (s_ "Show unix terminal");
 
271
         ]
 
272
    in
 
273
    form#add_section ~no_line:() "Hardware";
 
274
    let port_no =
 
275
      Gui_bricks.spin_byte ~lower:port_no_min ~upper:port_no_max ~step_incr:2
 
276
      ~packing:(form#add_with_tooltip (s_ "Number of router ports" )) port_no
 
277
    in
 
278
    let port_0_ip_config =
 
279
      Gui_bricks.spin_ipv4_address_with_cidr_netmask
 
280
        ~packing:(form#add_with_tooltip
 
281
                    ~just_for_label:()
 
282
                    (s_ "IPv4 configuration of the first router port (0)"))
 
283
        b1 b2 b3 b4 b5
 
284
    in
 
285
    form#add_section "Software";
 
286
    let distribution_variant_kernel =
 
287
      let packing_distribution =
 
288
        form#add_with_tooltip
 
289
          (s_ "GNU/Linux distribution installed on the router." )
 
290
      in
 
291
      let packing_variant      =
 
292
        form#add_with_tooltip
 
293
          (s_ "Initial hard disk state. The router will start by default with this variant of the chosen distribution." )
 
294
      in
 
295
      let packing_kernel =
 
296
        form#add_with_tooltip
 
297
          (s_ "Linux kernel version used for this router." )
 
298
      in
 
299
      let packing = (packing_distribution, packing_variant, packing_kernel) in
 
300
      Gui_bricks.make_combo_boxes_of_vm_installations
 
301
        ?distribution ?variant ?kernel ?updating
 
302
        ~packing
 
303
        vm_installations
 
304
    in
 
305
    form#add_section "Access";
 
306
    let show_unix_terminal =
 
307
      GButton.check_button
 
308
        ~active:show_unix_terminal
 
309
        ~packing:(form#add_with_tooltip (s_ "Do you want access the router also by a Unix terminal?" ))
 
310
        ()
 
311
    in
 
312
    (port_0_ip_config, port_no, distribution_variant_kernel, show_unix_terminal)
 
313
  in
 
314
  let get_widget_data () :'result =
 
315
    let name = name#text in
 
316
    let label = label#text in
 
317
    let port_0_ip_config =
 
318
      let s1 = int_of_float s1#value in
 
319
      let s2 = int_of_float s2#value in
 
320
      let s3 = int_of_float s3#value in
 
321
      let s4 = int_of_float s4#value in
 
322
      let s5 = int_of_float s5#value in
 
323
      ((s1,s2,s3,s4),s5)
 
324
    in
 
325
    let port_no = int_of_float port_no#value in
 
326
    let distribution  = distribution_variant_kernel#selected in
 
327
    let variant       = distribution_variant_kernel#slave0#selected in
 
328
    let kernel        = distribution_variant_kernel#slave1#selected in
 
329
    let variant = match variant with
 
330
    | "none" -> None
 
331
    | x      -> Some x
 
332
    in
 
333
    let show_unix_terminal = show_unix_terminal#active in
 
334
      { Data.name = name;
 
335
        Data.label = label;
 
336
        Data.port_0_ip_config = port_0_ip_config;
 
337
        Data.port_no = port_no;
 
338
        Data.distribution = distribution;
 
339
        Data.variant = variant;
 
340
        Data.kernel = kernel;
 
341
        Data.show_unix_terminal = show_unix_terminal;
 
342
        Data.old_name = old_name;
 
343
        }
 
344
 
 
345
  in
 
346
  (* The result of make is the result of the dialog loop (of type 'result option): *)
 
347
  Gui_bricks.Dialog_run.ok_or_cancel w ~ok_callback ~help_callback ~get_widget_data ()
 
348
 
 
349
 
 
350
(*-----*)
 
351
  WHERE
 
352
(*-----*)
 
353
 
 
354
 let help_callback =
 
355
   let title = (s_ "ADD OR MODIFY A ROUTER") in
 
356
   let msg   = (s_ "\
 
357
In this dialog window you can define the name of an IP router \
 
358
and set many parameters for it:\n\n\
 
359
- Label: a string appearing near the router icon in the network graph; \
 
360
this field is exclusively for graphic purposes, is not taken in consideration \
 
361
for the configuration.\n\
 
362
- Nb of Ports: the number of ports of the router (default 4); this number must \
 
363
not be increased without a reason, because the number of processes needed for the \
 
364
device emulation is proportional to his ports number.\n\n\
 
365
The emulation of this device is realised with the program 'quagga' derived from \
 
366
the project 'zebra'.\n\n\
 
367
Every interface of the router can be configured in the tab \
 
368
'Interfaces'. Once started, the router will answer to the telnet \
 
369
protocol on every configured interface, on the following tcp ports:\n\n\
 
370
zebra\t\t2601/tcp\t\t# zebra vty\n\
 
371
ripd\t\t\t2602/tcp\t\t# RIPd vty\n\
 
372
ripngd\t\t2603/tcp\t\t# RIPngd vty\n\
 
373
ospfd\t\t2604/tcp\t\t# OSPFd vty\n\
 
374
bgpd\t\t2605/tcp\t\t# BGPd vty\n\
 
375
ospf6d\t\t2606/tcp\t\t# OSPF6d vty\n\
 
376
isisd\t\t\t2608/tcp\t\t# ISISd vty\n\n\
 
377
Password: zebra")
 
378
   in Simple_dialogs.help title msg ;;
 
379
 
 
380
end
 
381
 
 
382
(*-----*)
 
383
  WHERE
 
384
(*-----*)
 
385
 
 
386
module Eval_forest_child = struct
 
387
 let try_to_add_router (network:User_level.network) ((root,childs):Xforest.tree) =
 
388
  try
 
389
   (match root with
 
390
    | ("router", attrs) ->
 
391
        let name  = List.assoc "name" attrs in
 
392
        let port_no = int_of_string (List.assoc "port_no" attrs) in
 
393
        Log.printf "Importing router \"%s\" with %d ports...\n" name port_no;
 
394
        let x = new User_level_router.router ~network ~name ~port_no () in
 
395
        x#from_tree ("router", attrs) childs;
 
396
        Log.printf "Router \"%s\" successfully imported.\n" name;
 
397
        true
 
398
 
 
399
   (* backward compatibility *)
 
400
   | ("device", attrs) ->
 
401
      let name  = List.assoc "name" attrs in
 
402
      let port_no = int_of_string (List.assoc "eth" attrs) in
 
403
      let kind = List.assoc "kind" attrs in
 
404
      (match kind with
 
405
      | "router" ->
 
406
          Log.printf "Importing router \"%s\" with %d ports...\n" name port_no;
 
407
          let r = new User_level_router.router ~network ~name ~port_no () in
 
408
          let x = (r :> User_level.node_with_ledgrid_and_defects) in
 
409
          x#from_tree ("device", attrs) childs ;
 
410
          Log.printf "Router \"%s\" successfully imported.\n" name;
 
411
          true
 
412
      | _ -> false
 
413
      )
 
414
   | _ -> false
 
415
   )
 
416
  with _ -> false
 
417
end (* module Eval_forest_child *)
 
418
 
 
419
 
 
420
(*-----*)
 
421
  WHERE
 
422
(*-----*)
 
423
 
 
424
 
 
425
module User_level_router = struct
 
426
 
 
427
class router
 
428
  ~(network:User_level.network)
 
429
  ~name
 
430
  ?(port_0_ip_config=Const.port_0_ip_config_default)
 
431
  ?label
 
432
  ?epithet
 
433
  ?variant
 
434
  ?kernel
 
435
  ?(show_unix_terminal=false)
 
436
  ?terminal
 
437
  ~port_no
 
438
  ()
 
439
  =
 
440
  let vm_installations = Disk.get_router_installations () in
 
441
  let network_alias = network in
 
442
  (* The ifconfig treeview wants a port 0 configuration at creation time:*)
 
443
  let ifconfig_port_row_completions =
 
444
     let (ipv4,cidr) = port_0_ip_config in (* the class parameter *)
 
445
     let netmask_string = (Ipv4.to_string (Ipv4.netmask_of_cidr cidr)) in
 
446
     [ ("port0",
 
447
            [ "IPv4 address", Treeview.Row_item.String (Ipv4.to_string ipv4);
 
448
              "IPv4 netmask", Treeview.Row_item.String netmask_string; ])
 
449
     ]
 
450
  in
 
451
 
 
452
  object (self) inherit OoExtra.destroy_methods ()
 
453
 
 
454
  inherit User_level.node_with_ledgrid_and_defects
 
455
    ~network
 
456
    ~name ?label ~devkind:`Router
 
457
    ~port_no
 
458
    ~port_no_min:Const.port_no_min
 
459
    ~port_no_max:Const.port_no_max
 
460
    ~port_prefix:"port"
 
461
    ()
 
462
    as self_as_node_with_ledgrid_and_defects
 
463
 
 
464
  inherit User_level.virtual_machine_with_history_and_ifconfig
 
465
    ~network:network_alias
 
466
    ?epithet ?variant ?kernel ?terminal
 
467
    ~history_icon:"router"
 
468
    ~ifconfig_device_type:"router"
 
469
    ~ifconfig_port_row_completions
 
470
    ~vm_installations
 
471
    ()
 
472
    as self_as_virtual_machine_with_history_and_ifconfig
 
473
 
 
474
  method polarity = User_level.MDI
 
475
  method string_of_devkind = "router"
 
476
  method ledgrid_label = "Router"
 
477
  method defects_device_type = "router"
 
478
 
 
479
  method dotImg iconsize =
 
480
   let imgDir = Initialization.Path.images in
 
481
   (imgDir^"ico.router."^(self#string_of_simulated_device_state)^"."^iconsize^".png")
 
482
 
 
483
  (** Get the full host pathname to the directory containing the guest hostfs
 
484
      filesystem: *)
 
485
  method hostfs_directory_pathname =
 
486
    let d = ((Option.extract !simulated_device) :> User_level.node Simulation_level.router) in
 
487
    d#hostfs_directory_pathname
 
488
 
 
489
  val mutable show_unix_terminal : bool = show_unix_terminal
 
490
  method get_show_unix_terminal = show_unix_terminal
 
491
  method set_show_unix_terminal x = show_unix_terminal <- x
 
492
 
 
493
  (** Create the simulated device *)
 
494
  method private make_simulated_device =
 
495
    let id = self#id in
 
496
    let cow_file_name, dynamically_get_the_cow_file_name_source =
 
497
      self#create_cow_file_name_and_thunk_to_get_the_source
 
498
    in
 
499
    let () =
 
500
     Log.printf
 
501
       "About to start the router %s\n  with filesystem: %s\n  cow file: %s\n  kernel: %s\n"
 
502
       self#name
 
503
       self#get_filesystem_file_name
 
504
       cow_file_name
 
505
       self#get_kernel_file_name
 
506
    in
 
507
    new Simulation_level.router
 
508
      ~parent:self
 
509
      ~kernel_file_name:self#get_kernel_file_name
 
510
      ?kernel_console_arguments:self#get_kernel_console_arguments
 
511
      ~filesystem_file_name:self#get_filesystem_file_name
 
512
      ~dynamically_get_the_cow_file_name_source
 
513
      ~cow_file_name
 
514
      ~states_directory:(self#get_states_directory)
 
515
      ~ethernet_interface_no:self#get_port_no
 
516
      ~umid:self#get_name
 
517
      ~id
 
518
      ~show_unix_terminal:self#get_show_unix_terminal
 
519
      ~unexpected_death_callback:self#destroy_because_of_unexpected_death
 
520
      ()
 
521
 
 
522
 
 
523
  (** Here we also have to manage cow files... *)
 
524
  method private gracefully_shutdown_right_now =
 
525
    self_as_node_with_ledgrid_and_defects#gracefully_shutdown_right_now;
 
526
    (* We have to manage the hostfs stuff (when in exam mode) and
 
527
       destroy the simulated device, so that we can use a new cow file the next time: *)
 
528
    Log.printf "Calling hostfs_directory_pathname on %s...\n" self#name;
 
529
    let hostfs_directory_pathname = self#hostfs_directory_pathname in
 
530
    Log.printf "Ok, we're still alive\n";
 
531
    (* If we're in exam mode then make the report available in the texts treeview: *)
 
532
    (if Command_line.are_we_in_exam_mode then begin
 
533
      let treeview_documents = Treeview_documents.extract () in
 
534
      Log.printf "Adding the report on %s to the texts interface\n" self#name;
 
535
      treeview_documents#import_report
 
536
        ~machine_or_router_name:self#name
 
537
        ~pathname:(hostfs_directory_pathname ^ "/report.html")
 
538
        ();
 
539
      Log.printf "Added the report on %s to the texts interface\n" self#name;
 
540
    end);
 
541
    (* ...And destroy, so that the next time we have to re-create the process command line
 
542
        can use a new cow file (see the make_simulated_device method) *)
 
543
    self#destroy_right_now
 
544
 
 
545
 
 
546
  (** Here we also have to manage LED grids and, for routers, cow files: *)
 
547
  method private poweroff_right_now =
 
548
    self_as_node_with_ledgrid_and_defects#poweroff_right_now;
 
549
    (* Destroy, so that the next time we have to re-create a simulated device,
 
550
       and we start with a new cow: *)
 
551
    self#destroy_right_now
 
552
 
 
553
  method to_tree =
 
554
   Forest.tree_of_leaf ("router", [
 
555
      ("name"     ,  self#get_name );
 
556
      ("label"   ,   self#get_label);
 
557
      ("distrib"  ,  self#get_epithet  );
 
558
      ("variant"  ,  self#get_variant_as_string);
 
559
      ("kernel"   ,  self#get_kernel   );
 
560
      ("show_unix_terminal" , string_of_bool (self#get_show_unix_terminal));
 
561
      ("terminal" ,  self#get_terminal );
 
562
      ("port_no"  ,  (string_of_int self#get_port_no))  ;
 
563
      ])
 
564
 
 
565
 (** A machine has just attributes (no childs) in this version. *)
 
566
 method eval_forest_attribute = function
 
567
  | ("name"     , x ) -> self#set_name x
 
568
  | ("label"    , x ) -> self#set_label x
 
569
  | ("distrib"  , x ) -> self#set_epithet x
 
570
  | ("variant"  , "") -> self#set_variant None
 
571
  | ("variant"  , x ) -> self#set_variant (Some x)
 
572
  | ("kernel"   , x ) -> self#set_kernel x
 
573
  | ("show_unix_terminal", x ) -> self#set_show_unix_terminal (bool_of_string x)
 
574
  | ("terminal" , x ) -> self#set_terminal x
 
575
  | ("port_no"  , x ) -> self#set_port_no  (int_of_string x)
 
576
  | _ -> () (* Forward-comp. *)
 
577
 
 
578
 method private get_assoc_list_from_ifconfig ~key =
 
579
   List.map
 
580
     (fun i -> (i,network#ifconfig#get_port_attribute_by_index self#get_name i key))
 
581
     (ListExtra.range 0 (self#get_port_no - 1))
 
582
 
 
583
 method get_mac_addresses  = self#get_assoc_list_from_ifconfig ~key:"MAC address"
 
584
 method get_ipv4_addresses = self#get_assoc_list_from_ifconfig ~key:"IPv4 address"
 
585
(* other: "MTU", "IPv4 netmask", "IPv4 broadcast", "IPv6 address" *)
 
586
 
 
587
 method get_port_0_ip_config =
 
588
  let name = self#get_name in
 
589
  let ipv4 =
 
590
    Ipv4.of_string
 
591
      (network#ifconfig#get_port_attribute_by_index
 
592
         name 0 "IPv4 address")
 
593
  in
 
594
  let cidr =
 
595
    Ipv4.cidr_of_netmask
 
596
      (Ipv4.netmask_of_string
 
597
         (network#ifconfig#get_port_attribute_by_index
 
598
          name 0 "IPv4 netmask"))
 
599
    in
 
600
  (ipv4, cidr)
 
601
 
 
602
 
 
603
 method set_port_0_ipv4_address (ipv4:Ipv4.t) =
 
604
   network#ifconfig#set_port_string_attribute_by_index
 
605
     self#get_name 0 "IPv4 address"
 
606
     (Ipv4.to_string ipv4);
 
607
 
 
608
 method set_port_0_ipv4_netmask_by_cidr cidr =
 
609
   let netmask_as_string = Ipv4.to_string (Ipv4.netmask_of_cidr cidr) in
 
610
   network#ifconfig#set_port_string_attribute_by_index
 
611
     self#get_name 0 "IPv4 netmask"
 
612
     netmask_as_string
 
613
 
 
614
 method set_port_0_ip_config port_0_ip_config =
 
615
   let (ipv4,cidr) = port_0_ip_config in
 
616
   self#set_port_0_ipv4_address ipv4;
 
617
   self#set_port_0_ipv4_netmask_by_cidr cidr;
 
618
 
 
619
 method update_router_with ~name ~label ~port_0_ip_config ~port_no ~kernel ~show_unix_terminal =
 
620
   (* first action: *)
 
621
   self_as_virtual_machine_with_history_and_ifconfig#update_virtual_machine_with ~name ~port_no kernel;
 
622
   (* then we can set the object property "name" (read by #get_name): *)
 
623
   self_as_node_with_ledgrid_and_defects#update_with ~name ~label ~port_no;
 
624
   self#set_port_0_ip_config port_0_ip_config;
 
625
   self#set_show_unix_terminal show_unix_terminal;
 
626
 
 
627
end;;
 
628
 
 
629
end (* module User_level_router *)
 
630
 
 
631
(*-----*)
 
632
  WHERE
 
633
(*-----*)
 
634
 
 
635
module Simulation_level = struct
 
636
(** A router: just a [machine_or_router] with [router = true] *)
 
637
class ['parent] router =
 
638
  fun ~(parent:'parent)
 
639
      ~dynamically_get_the_cow_file_name_source
 
640
      ~(cow_file_name)
 
641
      ~states_directory
 
642
      ~(kernel_file_name)
 
643
      ?(kernel_console_arguments)
 
644
      ~(filesystem_file_name)
 
645
      ~(ethernet_interface_no)
 
646
      ?umid
 
647
      ~id
 
648
      ~show_unix_terminal
 
649
      ~unexpected_death_callback
 
650
      () ->
 
651
object(self)
 
652
  inherit ['parent] Simulation_level.machine_or_router
 
653
      ~parent
 
654
      ~router:true
 
655
      ~filesystem_file_name(* :"/usr/marionnet/filesystems/router.debian.lenny.sid.fs" *)
 
656
      ~kernel_file_name
 
657
      ?kernel_console_arguments
 
658
      ~dynamically_get_the_cow_file_name_source
 
659
      ~cow_file_name
 
660
      ~states_directory
 
661
      ~ethernet_interface_no
 
662
      ~memory:Const.memory_default
 
663
      ?umid
 
664
      (* Change this when debugging the router device *)
 
665
      ~console:"none" (* To do: this should be "none" for releases and "xterm" for debugging *)
 
666
      ~id
 
667
      ~show_unix_terminal
 
668
      ~xnest:false
 
669
      ~unexpected_death_callback
 
670
      ()
 
671
      as super
 
672
  method device_type = "router"
 
673
end
 
674
 
 
675
end (* module Simulation_level *)
 
676
 
 
677
 
 
678
(** Just for testing: *)
 
679
let test = Dialog_add_or_update.make