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

« back to all changes in this revision

Viewing changes to hub.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) 2010  Jean-Vincent Loddo
 
3
   Copyright (C) 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
 
 
19
(** "Hub" component implementation. *)
 
20
 
 
21
#load "where_p4.cmo"
 
22
;;
 
23
 
 
24
open Gettext
 
25
 
 
26
(* Hub related constants: *)
 
27
(* TODO: make it configurable! *)
 
28
module Const = struct
 
29
 let port_no_default = 4
 
30
 let port_no_min = 4
 
31
 let port_no_max = 16
 
32
end
 
33
 
 
34
(* The type of data exchanged with the dialog: *)
 
35
module Data = struct
 
36
type t = {
 
37
  name        : string;
 
38
  label       : string;
 
39
  port_no     : int;
 
40
  old_name    : string;
 
41
  }
 
42
 
 
43
let to_string t = "<obj>" (* TODO? *)
 
44
end (* Data *)
 
45
 
 
46
module Make_menus (Params : sig
 
47
  val st      : State.globalState
 
48
  val packing : [ `toolbar of GButton.toolbar | `menu_parent of Menu_factory.menu_parent ]
 
49
 end) = struct
 
50
 
 
51
  open Params
 
52
 
 
53
  module Toolbar_entry = struct
 
54
   let imagefile = "ico.hub.palette.png"
 
55
   let tooltip   = (s_ "Hub")
 
56
   let packing   = Params.packing
 
57
  end
 
58
 
 
59
  module Add = struct
 
60
    include Data
 
61
 
 
62
    let key = Some GdkKeysyms._H
 
63
 
 
64
    let ok_callback t = Gui_bricks.Ok_callback.check_name t.name t.old_name st#network#name_exists t
 
65
 
 
66
    let dialog () =
 
67
      let name = st#network#suggestedName "H" in
 
68
      Dialog_add_or_update.make ~title:(s_ "Add hub") ~name ~ok_callback ()
 
69
 
 
70
    let reaction { name = name; label = label; port_no = port_no } =
 
71
      let action () = ignore (new User_level_hub.hub ~network:st#network ~name ~label ~port_no ()) in
 
72
      st#network_change action ();
 
73
 
 
74
  end
 
75
 
 
76
  module Properties = struct
 
77
    include Data
 
78
    let dynlist () = st#network#get_nodes_that_can_startup ~devkind:`Hub ()
 
79
 
 
80
    let dialog name () =
 
81
     let d = (st#network#get_node_by_name name) in
 
82
     let title = (s_ "Modify hub")^" "^name in
 
83
     let label = d#get_label in
 
84
     let port_no = d#get_port_no in
 
85
     let port_no_min = st#network#port_no_lower_of (d :> User_level.node) in
 
86
     Dialog_add_or_update.make ~title ~name ~label ~port_no ~port_no_min ~ok_callback:Add.ok_callback ()
 
87
 
 
88
    let reaction { name = name; label = label; port_no = port_no; old_name = old_name; } =
 
89
      let d = (st#network#get_node_by_name old_name) in
 
90
      let h = ((Obj.magic d):> User_level_hub.hub) in
 
91
      let action () = h#update_with ~name ~label ~port_no in
 
92
      st#network_change action ();
 
93
 
 
94
  end
 
95
 
 
96
  module Remove = struct
 
97
    type t = string (* just the name *)
 
98
    let to_string = (Printf.sprintf "name = %s\n")
 
99
 
 
100
    let dynlist = Properties.dynlist
 
101
 
 
102
    let dialog name () =
 
103
      Gui_bricks.Dialog.yes_or_cancel_question
 
104
        ~title:(s_ "Remove")
 
105
        ~markup:(Printf.sprintf (f_ "Are you sure that you want to remove %s\nand all the cables connected to this %s?") name (s_ "hub"))
 
106
        ~context:name
 
107
        ()
 
108
 
 
109
    let reaction name =
 
110
      let d = (st#network#get_node_by_name name) in
 
111
      let h = ((Obj.magic d):> User_level_hub.hub) in
 
112
      let action () = h#destroy in
 
113
      st#network_change action ();
 
114
 
 
115
  end
 
116
 
 
117
  module Startup = struct
 
118
    type t = string (* just the name *)
 
119
    let to_string = (Printf.sprintf "name = %s\n")
 
120
    let dynlist    = Properties.dynlist
 
121
    let dialog     = Menu_factory.no_dialog_but_simply_return_name
 
122
    let reaction name = (st#network#get_node_by_name name)#startup
 
123
 
 
124
  end
 
125
 
 
126
  module Stop = struct
 
127
    type t = string (* just the name *)
 
128
    let to_string = (Printf.sprintf "name = %s\n")
 
129
    let dynlist () = st#network#get_nodes_that_can_gracefully_shutdown ~devkind:`Hub ()
 
130
    let dialog = Menu_factory.no_dialog_but_simply_return_name
 
131
    let reaction name = (st#network#get_node_by_name name)#gracefully_shutdown
 
132
 
 
133
  end
 
134
 
 
135
  module Suspend = struct
 
136
    type t = string (* just the name *)
 
137
    let to_string = (Printf.sprintf "name = %s\n")
 
138
    let dynlist () = st#network#get_nodes_that_can_suspend ~devkind:`Hub ()
 
139
    let dialog = Menu_factory.no_dialog_but_simply_return_name
 
140
    let reaction name = (st#network#get_node_by_name name)#suspend
 
141
 
 
142
  end
 
143
 
 
144
  module Resume = struct
 
145
    type t = string (* just the name *)
 
146
    let to_string = (Printf.sprintf "name = %s\n")
 
147
    let dynlist () = st#network#get_nodes_that_can_resume ~devkind:`Hub ()
 
148
    let dialog = Menu_factory.no_dialog_but_simply_return_name
 
149
    let reaction name = (st#network#get_node_by_name name)#resume
 
150
 
 
151
  end
 
152
 
 
153
 module Create_entries =
 
154
  Gui_toolbar_COMPONENTS_layouts.Layout_for_network_node (Params) (Toolbar_entry) (Add) (Properties) (Remove) (Startup) (Stop) (Suspend) (Resume)
 
155
 
 
156
 (* Subscribe this kind of component to the network club: *)
 
157
 st#network#subscribe_a_try_to_add_procedure Eval_forest_child.try_to_add_hub;
 
158
 
 
159
end
 
160
 
 
161
(*-----*)
 
162
  WHERE
 
163
(*-----*)
 
164
 
 
165
module Dialog_add_or_update = struct
 
166
 
 
167
(* This function may be useful for testing the widget creation without
 
168
   recompiling the whole project. *)
 
169
let make
 
170
 ?(title="Add hub")
 
171
 ?(name="")
 
172
 ?label
 
173
 ?(port_no=Const.port_no_default)
 
174
 ?(port_no_min=Const.port_no_min)
 
175
 ?(port_no_max=Const.port_no_max)
 
176
 ?(help_callback=help_callback) (* defined backward with "WHERE" *)
 
177
 ?(ok_callback=(fun data -> Some data))
 
178
 ?(dialog_image_file=Initialization.Path.images^"ico.hub.dialog.png")
 
179
 () :'result option =
 
180
  let old_name = name in
 
181
  let (w,_,name,label) =
 
182
    Gui_bricks.Dialog_add_or_update.make_window_image_name_and_label
 
183
      ~title
 
184
      ~image_file:dialog_image_file
 
185
      ~image_tooltip:(s_ "Hub")
 
186
      ~name
 
187
      ~name_tooltip:(s_ "Hub name. This name must be unique in the virtual network. Suggested: H1, H2, ... ")
 
188
      ?label
 
189
      ()
 
190
  in
 
191
  let port_no =
 
192
    let vbox = GPack.vbox ~homogeneous:false ~border_width:20 ~spacing:10 ~packing:w#vbox#add () in
 
193
    let form =
 
194
      Gui_bricks.make_form_with_labels
 
195
        ~packing:vbox#add
 
196
        [(s_ "Ports number")]
 
197
    in
 
198
    let port_no =
 
199
      Gui_bricks.spin_byte
 
200
        ~packing:(form#add_with_tooltip (s_ "Hub ports number"))
 
201
        ~lower:port_no_min ~upper:port_no_max ~step_incr:2
 
202
        port_no
 
203
    in
 
204
    port_no
 
205
  in
 
206
 
 
207
  let get_widget_data () :'result =
 
208
    let name = name#text in
 
209
    let label = label#text in
 
210
    let port_no = int_of_float port_no#value in
 
211
      { Data.name = name;
 
212
        Data.label = label;
 
213
        Data.port_no = port_no;
 
214
        Data.old_name = old_name;
 
215
        }
 
216
  in
 
217
  (* The result of make is the result of the dialog loop (of type 'result option): *)
 
218
  Gui_bricks.Dialog_run.ok_or_cancel w ~ok_callback ~help_callback ~get_widget_data ()
 
219
 
 
220
(*-----*)
 
221
  WHERE
 
222
(*-----*)
 
223
 
 
224
 let help_callback =
 
225
   let title = (s_ "ADD OR MODIFY A HUB") in
 
226
   let msg   = (s_ "\
 
227
In this dialog window you can define the name of an Ethernet HUB \
 
228
and set parameters for it:\n\
 
229
- Label: a string appearing near the hub icon in the network graph; it may \
 
230
allow, for example, to know at a glance the Ethernet network realized by the device; \
 
231
this field is exclusively for graphic purposes, is not taken in consideration \
 
232
for the configuration.\n\
 
233
- Nb of Ports: the number of ports of the hub (default 4); this number must \
 
234
not be increased without a reason, because the number of processes needed for the \
 
235
device emulation is proportional to his ports number.")
 
236
   in Simple_dialogs.help title msg
 
237
 
 
238
end
 
239
 
 
240
(*-----*)
 
241
  WHERE
 
242
(*-----*)
 
243
 
 
244
module Eval_forest_child = struct
 
245
 
 
246
 let try_to_add_hub (network:User_level.network) ((root,childs):Xforest.tree) =
 
247
  try
 
248
   (match root with
 
249
    | ("hub", attrs) ->
 
250
        let name  = List.assoc "name" attrs in
 
251
        let port_no = int_of_string (List.assoc "port_no" attrs) in
 
252
        Log.printf "Importing hub \"%s\" with %d ports...\n" name port_no;
 
253
        let x = new User_level_hub.hub ~network ~name ~port_no () in
 
254
        x#from_tree ("hub", attrs) childs;
 
255
        Log.printf "Hub \"%s\" successfully imported.\n" name;
 
256
        true
 
257
 
 
258
    (* backward compatibility *)
 
259
    | ("device", attrs) ->
 
260
        let name  = List.assoc "name" attrs in
 
261
        let port_no = try int_of_string (List.assoc "eth" attrs) with _ -> Const.port_no_default in
 
262
        let kind = List.assoc "kind" attrs in
 
263
        (match kind with
 
264
        | "hub" ->
 
265
            Log.printf "Importing hub \"%s\" with %d ports...\n" name port_no;
 
266
            let x = new User_level_hub.hub ~network ~name ~port_no () in
 
267
            x#from_tree ("hub", attrs) childs; (* Just for the label... *)
 
268
            Log.printf "This is an old project: we set the user port offset to 1...\n";
 
269
            network#defects#change_port_user_offset ~device_name:name ~user_port_offset:1;
 
270
            Log.printf "Hub \"%s\" successfully imported.\n" name;
 
271
            true
 
272
        | _ -> false
 
273
        )
 
274
   | _ -> false
 
275
   )
 
276
  with _ -> false
 
277
 
 
278
end (* module Eval_forest_child *)
 
279
 
 
280
 
 
281
(*-----*)
 
282
  WHERE
 
283
(*-----*)
 
284
 
 
285
 
 
286
module User_level_hub = struct
 
287
 
 
288
class hub =
 
289
 
 
290
 fun ~network
 
291
     ~name
 
292
     ?label
 
293
     ~port_no
 
294
     () ->
 
295
  object (self) inherit OoExtra.destroy_methods ()
 
296
 
 
297
  inherit
 
298
    User_level.node_with_ledgrid_and_defects
 
299
      ~network
 
300
      ~name ?label ~devkind:`Hub
 
301
      ~port_no
 
302
      ~port_no_min:Const.port_no_min
 
303
      ~port_no_max:Const.port_no_max
 
304
      ~user_port_offset:1 (* in order to have a perfect mapping with VDE *)
 
305
      ~port_prefix:"port"
 
306
      ()
 
307
    as self_as_node_with_ledgrid_and_defects
 
308
  method ledgrid_label = "Hub"
 
309
  method defects_device_type = "hub"
 
310
  method polarity = User_level.MDI_X
 
311
  method string_of_devkind = "hub"
 
312
 
 
313
  method dotImg iconsize =
 
314
   let imgDir = Initialization.Path.images in
 
315
   (imgDir^"ico.hub."^(self#string_of_simulated_device_state)^"."^iconsize^".png")
 
316
 
 
317
  (** Create the simulated device *)
 
318
  method private make_simulated_device =
 
319
    let hublet_no = self#get_port_no in
 
320
    let unexpected_death_callback = self#destroy_because_of_unexpected_death in
 
321
    ((new Simulation_level_hub.hub
 
322
        ~parent:self
 
323
        ~hublet_no
 
324
        ~unexpected_death_callback
 
325
        ()) :> User_level.node Simulation_level.device)
 
326
 
 
327
  method to_tree =
 
328
   Forest.tree_of_leaf ("hub", [
 
329
     ("name"     ,  self#get_name );
 
330
     ("label"    ,  self#get_label);
 
331
     ("port_no"  ,  (string_of_int self#get_port_no))  ;
 
332
     ])
 
333
 
 
334
  method eval_forest_attribute = function
 
335
  | ("name"     , x ) -> self#set_name x
 
336
  | ("label"    , x ) -> self#set_label x
 
337
  | ("port_no"  , x ) -> self#set_port_no (int_of_string x)
 
338
  | _ -> () (* Forward-comp. *)
 
339
 
 
340
end (* class hub *)
 
341
 
 
342
end (* module User_level_hub *)
 
343
 
 
344
(*-----*)
 
345
  WHERE
 
346
(*-----*)
 
347
 
 
348
module Simulation_level_hub = struct
 
349
 
 
350
(** A hub: just a [hub_or_switch] with [hub = true] *)
 
351
class ['parent] hub =
 
352
  fun ~parent
 
353
      ~hublet_no
 
354
      ?(last_user_visible_port_index:int option)
 
355
      ~unexpected_death_callback
 
356
      () ->
 
357
object(self)
 
358
  inherit ['parent] Simulation_level.hub_or_switch
 
359
      ~parent
 
360
      ~hublet_no
 
361
      ?last_user_visible_port_index
 
362
      ~hub:true
 
363
      ~unexpected_death_callback
 
364
      ()
 
365
      as super
 
366
  method device_type = "hub"
 
367
end;;
 
368
 
 
369
end (* module Simulation_level_hub *)
 
370
 
 
371
(** Just for testing: *)
 
372
let test = Dialog_add_or_update.make