Giter Site home page Giter Site logo

ocaml-openflow's People

Contributors

adferguson avatar arjunguha avatar basus avatar ekotlikoff avatar fugitifduck avatar jcollard avatar jnfoster avatar lvanbever avatar mcanini avatar mor1 avatar nimishgupta avatar reitblatt avatar seliopou avatar smolkaj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ocaml-openflow's Issues

disconnect events not propagated for OpenFlow 1.0 switches

when an OpenFlow 1.0 switch disconnects, no event is propagated up to any users of OpenFlow0x01_Platform. this is in stark contrast to the SwitchDisconnected exception thrown by OpenFlow0x04_Platform.

without such an event/exception, OpenFlow 1.0 controllers (e.g., NetCore) cannot release any resources for a disconnected switch, or otherwise determine that a switch is no longer there.

NXM support

Hi there! Great project! :)

I was wondering whether there are any plans to add support for the Open vSwitch extensions from Nicira (NXM), such as additional matches with masks, multiple tables, and the "learn" action?

Malformed flow mod on ipSrc/ipDst match

I'm trying to generate rules that match Input Port and IP Src and IP DST. I noticed that the rules weren't getting correctly installed on our Pronto switch, in particular only the in_port was installed as a match. Poking at the stream with Wireshark it looks like the FlowMods are being malformed. Wireshark tells me "Error/Malformed: Trying to fetch an IPv6 address with length 4".

If I print the flowtable prior to invoking SDN.setup_flow_table it shows me the correct match, which leads to believe there might a bug in Ocaml-OpenFlow. This is for OpenFlow 0x01. Help?

Outstanding pull requests?

Not to sound pushy, but can someone review and merge in the outstanding pull requests now that the PLDI rush is over? Some of them have been sitting around for almost two weeks.

please support interleaved send/recv

hi all,

while doing some throughput testing, I noticed that LWT lacks fairness between competing light weight threads. because OCaml lacks support for hardware parallelism, this situation can easily lead to starvation.

the scenario is as follows:

  1. we have an OpenFlow switch which is sending many packets to the controller (eg, ARP requests)
  2. for every packet received by the controller, the controller emits a packet (eg, ARP replies)

this is the design of a basic ARP cache.

in OpenFlow0x01_Switch.ml, we have two light weight threads: recv_thread and send_thread which should be responsible for parts 1 and 2 above. each is implemented as an infinite recursion.

the problem is that LWT appears by default to only yield to a different thread when a system call doesn't return right away. therefore, because there is always something in the receive buffer, recv_thread hogs the sole OCaml hardware thread, and send_thread starves.

it would be a big improvement if recv_thread and send_thread were interleaved to prevent starvation in such scenarios. of course, this only solves the problem for a single switch, and for as many light-weight threads as the authors see fit to interleave -- the proper solution is to have a language with hardware parallelism. :-(

thank you,
Andrew

PS -- to see / reproduce this, I have two xterms on the same host in mininet. in the first xterm, I do arping -c 200 -w 500000 h2 while in the second, I have tcpdump -i h1-eth0 ... from the tcpdump, we can clearly see that all 200 arp requests are received before the 200 replies are sent (even though our my logging emits an arp reply for every arp request incrementally). hence, arping reports that 100% of the arp queries are unanswered (since they arrive after the 200 requests have all been sent).

Create an OutputPort data type for use in Output actions

Currently the PseudoPort data type contains a variant for the special controller port. That constructor takes an integer which is the maximum number of bytes of the packet that should be sent to the controller. The only place where the controller PseudoPort should be used is in an Output action, and that's also the only place that handles the length parameter properly. That's mentioned in the code here, and is also clear from the OpenFlow standard, § A.2.5 Action Structures, as the max_length is part of the ofp_action_output struct, not the port representation.

PseudoPort should not include the Controller variant. That should be removed, and a new data type OutputPort should be introduced which is either a PseudoPort or a controller with an int parameter. That should only be used in the Output action.

The comment in fa51a3f is relevant to this issue.

increased handshake stalls after merge of #34

the only downside to this new handshake design in #34 is that I am seeing a much higher rate of handshakes stalling. it appears there is not enough asynchrony / light-weight threading in the new design.

I can reproduce handshake stalls regularly (although not consistently) with a mininet configuration like the following:

$ sudo mn --controller=remote --topo=tree,depth4=2,fanout=2 --mac --arp --switch=user

the userspace switch is better at triggering this than Open vSwitch.

this problem is related to @arjunguha's comment: https://github.com/frenetic-lang/ocaml-openflow/blob/master/lib/OpenFlow0x01_Platform.ml#L82

in my testing, the hanshake stalls manifest as uncaught exceptions when the controller then proceeds to write to a socket has been closed by the switch after timing-out.

Can someone who is an expert in LWT & Ocaml pseudo-threads examine and resolve this please?

thank you,
Andrew

configure script

Is missing. But there should be one, because there are options, like --enable-tests...

PortDescriptions are not parsed correctly

It seems as though the port_no in PortDescriptions received from switches are always set to 512, which indicates some sort of parsing error.

This is happening in the reactive branch of this repository, conjunction with the reactive branch in the frenetic repository.

Dies on too many open files

Running on mininet with 80 switches crashes with the following backtrace:

("unhandled exception"
 ((lib/monitor.ml.Error_
   ((exn (Unix.Unix_error "Too many open files" accept "((fd 4))"))
    (backtrace
     ("Raised at file \"lib/core_unix.ml\", line 48, characters 11-42"
      "Called from file \"lib/core_unix.ml\", line 2125, characters 17-40"
      "Called from file \"lib/raw_fd.ml\", line 268, characters 11-25"
      "Re-raised at file \"lib/unix_syscalls.ml\", line 786, characters 28-31"
      "Called from file \"lib/deferred.ml\", line 119, characters 6-13"
      "Called from file \"lib/raw_deferred.ml\", line 48, characters 2-10"
      "Called from file \"lib/unix_syscalls.ml\", line 790, characters 4-57"
      "Called from file \"lib/monitor.ml\", line 169, characters 25-32"
      "Called from file \"lib/jobs.ml\", line 213, characters 10-13" ""))
    (monitor
     (((name try_with) (here ()) (id 24421) (has_seen_error true)
       (someone_is_listening true) (kill_index 0))))))
  (Pid 94636)))
libgcc_s.so.1 must be installed for pthread_cancel to work
Aborted

Delete all flows on empty OVS causes an error message

Delete all flows on empty OVS causes an error message. I think it is safe to simply ignore it. It sounds safer to always try sending the delete all flows at start time.

This request ...

Openflow Protocol
    Header
        Version: 0x04
        Type: Flow mod (CSM) - OFPT_FLOW_MOD (14)
        Length: 56
        Transaction ID: 0
    Flow Mod
        Cookie: 0x0000000000000000
        Cookie Mask: 0x0000000000000000
        Table ID: 0
        Command: Delete all matching flows - OFPFC_DELETE (0x03)
        Idle Timeout: 0
        Hard Timeout: 0
        Priority: 0
        Buffer ID: 0xffffffff
        Output Port: 0
        Output Group: 0
        Flags: 0x0000
            0000 0000 0000 0... = Reserved: Not set
            .... .... .... ...0 = Send flow removed message when flow expires or is deleted: Not set
            .... .... .... ..0. = Check for overlapping entries first: Not set
            .... .... .... .0.. = Reset flow packet and byte counts: Not set
        Padding
        Match
            Type: OpenFlow Extensible Match - OFPMT_OXM (0x0001)
            Length: 4
            Padding

Triggers this error:

Openflow Protocol
    Header
        Version: 0x04
        Type: Error (SM) - OFPT_ERROR (1)
        Length: 68
        Transaction ID: 0
    Error
        Type: Problem modifying flow entry - OFPET_FLOW_MOD_FAILED (5)
        Code: Unspecified error - OFPFMFC_UNKNOWN (0x0000)
        Data: 040e00380000000000000000000000000000000000000000...

cleanup suggestion: Capabilities / capabilities types

hey all,

I noticed that OpenFlow 0x04 and OpenFlow 0x01 have divergent and overlapping coverage for switch capabilities.

for example, 0x01 has SwitchFeatures.Capabilities while 0x04 has both Capabilities and uses types for OpenFlow0x04_Core (flow_stats, table_stats, etc.)

basically, the work to migrate 0x04 to the 0x01-style SwitchFeatures was not completed for the Capabilities elements.

cheers,
Andrew

"unrealizable modification"

Compiling this local policy:

filter port = 0; (vlanId := 65535; port := 1) |
filter port = 1; (vlanId := 65535; port := 0)

generates this flowtable:

[{pattern={InPort=0,action=SetField(Vlan,65535); OutputPort(1),
               cookie=0,idle_timeout=Permanent,hard_timeout=Permanent}
              {pattern={InPort=1,action=SetField(Vlan,65535); OutputPort(0),
              cookie=0,idle_timeout=Permanent,hard_timeout=Permanent}]

And causes this error:

Fatal error: exception Invalid_argument("unrealizable modification")
Raised at file "lib/ModComposition.ml", line 52, characters 29-73
Called from file "lib/ModComposition.ml", line 59, characters 10-38
Called from file "lib/HighLevelSwitch_common.ml", line 49, characters 6-24
Called from file "lib/HighLevelSwitch_common.ml", line 54, characters 19-38
Called from file "lib/HighLevelSwitch0x04.ml", line 160, characters 43-78
Called from file "lib/HighLevelSwitch0x04.ml", line 243, characters 19-58
Called from file "list.ml", line 57, characters 20-23
Called from file "lib/HighLevelSwitch0x04.ml", line 247, characters 18-42
Called from file "lib/Controller.ml", line 21, characters 11-50

Build broken with asnyc 111.13?

I just did an opam update, in the process pulling in async versino 111.13.00, and building ocaml-openflow now fails with:

ocaml setup.ml -build -j 4
Finished, 0 targets (0 cached) in 00:00:00.
+ ocamlfind ocamlc -c -g -I lib -syntax camlp4o -thread -package cstruct.syntax -package cstruct -package str -package sexplib.syntax -package cstruct.async -package packet -package async -package core -package threads -I async -I lib -o async/Async_OpenFlow_Platform.cmo async/Async_OpenFlow_Platform.ml
File "async/Async_OpenFlow_Platform.ml", line 97, characters 48-61:
Error: This expression has type
         ([> `Allow ] as 'a) Async_kernel.Deferred.t =
           'a Async_kernel.Ivar.Deferred.t
       but an expression was expected of type
         Impl.Client_id.t ->
         [ `Allow | `Deny of string option ] Async_extra.Import.Deferred.t
Command exited with code 2.
Compilation unsuccessful after building 82 targets (80 cached) in 00:00:00.
E: Failure("Command ''/home/basus/.opam/4.01.0/bin/ocamlbuild' lib/openflow.cma lib/openflow.cmxa lib/openflow.a lib/openflow.cmxs async/async.cma async/async.cmxa async/async.a async/async.cmxs examples/Learning_Switch.byte -use-ocamlfind -tag debug -j 4' terminated with error code 10")
make: *** [build] Error 1

I'm building the current HEAD of master and the build succeeds on a a different machine with async version 109.53.02.

Check physical ports are in valid range

While different version of OpenFlow use different sized ints to represent ports, the standard only uses a certain range of values within those ints to represent physical ports. When mapping OutputPort n from the abstraction layer each concrete version implementation should check that the port is with in the valid physical range.

The same holds for Enqueue(pport_id, queue_id) actions, when supported.

Speed up the build

With the introduction of async and core as dependencies, the travis-ci build went from taking several minutes to somewhere around half an hour. Find a way to get this time back down to single-digit minutes.

Crash for OpenFlow 1.0 switches when disconnect during write

hey Freneticians,

I got a crash in NetCore when a switch disconnected, apparently during a write.

while OpenFlow0x04_Platform.ml seems to have a fix for this (ie, send_to_switch_fd has error handling), OpenFlow0x01_Platform.ml does not (and neither of the _Switch.ml versions)

on the other hand, the stacktrace below does not list OpenFlow0x01_Platform.ml, so I'm not sure whether the error handling should be in OpenFlow0x01_Switch.ml directly? (or is that just how LWT hides the root cause?)

thanks!
Andrew

Fatal error: exception Unix.Unix_error(Unix.EBADF, "check_descriptor", "")
Raised at file "src/unix/lwt_unix.ml", line 361, characters 15-67
Called from file "src/unix/lwt_unix.ml", line 552, characters 2-21
Called from file "lib/OpenFlow0x01_Switch.ml", line 42, characters 13-50
Called from file "lib/OpenFlow0x01_Switch.ml", line 126, characters 12-47
Called from file "src/core/lwt.ml", line 646, characters 66-69
Ocaml exiting~
LWT exiting~

Not generating flowmods for OpenFlow 1.3

I'm trying to use ocaml-openflow with some hardware switches running openvswitch and OpenFlow 1.3. The switches connect properly but it seems like the SDN.setup_flow_table function does not correctly send out flow mods. I've looked at the links with Wireshark and I can see regular Echo Request and Reply messages, but no flow mods. It also seems like the setup_flow_table function does not return.

Add Controller action to SDN_Types

SDN_Types currently only allows sending packets to physical locations. Add support for sending to the controller while specifying number of bytes that should be sent.

please handle OpenFlow error messages sensibly

copy-pasta from Andrew's issue on frenetic:

hi all,

I recently realized that NetCore silently ignores OpenFlow error messages (ie, ErrorMsg from ocaml-openflow) received from the switch. it appears that NetKat is the same.

at the very least, please log these messages, and honestly, during development, I would prefer to see the controller abort due to many types of errors (eg, OFPFMFC_ALL_TABLES_FULL or OFPFMFC_BAD_COMMAND) rather than silently pretending that the policy had been installed correctly.

handling the OpenFlow error messages sensibly greatly simplifies the task of debugging a policy which is not functioning correctly because of switch limitations.

thank you,
Andrew

second crash type when switch disconnects

when an OpenFlow 1.0 switch disconnects abruptly, we eventually see OpenFlow0x01_Switch.ml's disconnect function called as send_thread received "false" from swend_to"_switch_fd.

the disconnect function throws an error from the Lwt_unix.close call. unfortunately, I can't figure out how to use try_lwt to catch the error. it would be great if someone with better Ocaml-foo than me could prevent this exception from crashing the controller.

the backtrace I get is just:

lwt_unix.ml 361: raise (Unix.Unix_error (Unix.EBADF, "check_descriptor", ""))
lwt_unix.ml 493: check_descriptor ch;

if it's helpful, here are some steps to reproduce via Flowlog: tnelson/FlowLog#29

should retry if write does not write all the bytes

in send_to_switch_fd -- https://github.com/frenetic-lang/ocaml-openflow/blob/master/lib/OpenFlow0x01_Switch.ml#L39 -- we see the following code:

let msg_len = String.length msg_buf in
  lwt sent = Lwt_unix.write sock msg_buf 0 msg_len in
  Lwt.return (sent = msg_len)

hence, it returns false if sent < msg_len which can occur if the socket's receiver is simply slower than the controller. in this case, ocaml-openflow should retry the send from where it left off, not disconnect the switch (!!) when it gets false back from this function: https://github.com/frenetic-lang/ocaml-openflow/blob/master/lib/OpenFlow0x01_Switch.ml#L129 ... as described in the manpage, http://linux.die.net/man/2/write, -1 indicates an actual error occurred (which LWT might turn into an exception? I'm just guessing here)

this is similar to the need to call recv multiple times if you get less than you expect from the buffer. that particular case is handled correctly for OpenFlow 1.3 switches only (unfortunately) via the SafeSocket wrapper: https://github.com/frenetic-lang/ocaml-openflow/blob/master/lib/OpenFlow0x04_Misc.ml#L107

you can reproduce this easily by sending a policy with O(1000) rules to a hardware switch. one band-aid for this problem is to turn off Nagle's algorithm by setting TCP_NODELAY to true on the switch socket. this, at least, will OpenFlow messages to the switch with less delay, giving it a better chance of keeping up with the controller. hence, enabling TCP_NODELAY may be worth doing in general (so far, it is helping my use case)

thanks,
Andrew

Fix 64-bit issues in VInt

The VInt module assumes that the int type is at most 32 bits. On 64-bit architectures this is not the case, and leads to runtime errors.

Implement switch discovery using probe packets

LLDP exists for this purpose, and has OCaml implementations here, here, and here.

Alternatively, use a controller-specific protocol. Every time a new port comes up on a switch, send the switchId and portId in an ethernet packet through that port. If a host is on the other side, it may drop it. If a switch is on the other side, it'll send the packet to the controller as a PACKET_IN with receivingswitchId and portId information, as well as the payload.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.