{"action":"created","issue":{"url":"https://api.github.com/repos/coreemu/core/issues/150","repository_url":"https://api.github.com/repos/coreemu/core","labels_url":"https://api.github.com/repos/coreemu/core/issues/150/labels{/name}","comments_url":"https://api.github.com/repos/coreemu/core/issues/150/comments","events_url":"https://api.github.com/repos/coreemu/core/issues/150/events","html_url":"https://github.com/coreemu/core/issues/150","id":315539782,"number":150,"title":"Making the OvsService easier to use","user":{"login":"andreas-ibm","id":18004999,"avatar_url":"https://avatars2.githubusercontent.com/u/18004999?v=4","gravatar_id":"","url":"https://api.github.com/users/andreas-ibm","html_url":"https://github.com/andreas-ibm","followers_url":"https://api.github.com/users/andreas-ibm/followers","following_url":"https://api.github.com/users/andreas-ibm/following{/other_user}","gists_url":"https://api.github.com/users/andreas-ibm/gists{/gist_id}","starred_url":"https://api.github.com/users/andreas-ibm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andreas-ibm/subscriptions","organizations_url":"https://api.github.com/users/andreas-ibm/orgs","repos_url":"https://api.github.com/users/andreas-ibm/repos","events_url":"https://api.github.com/users/andreas-ibm/events{/privacy}","received_events_url":"https://api.github.com/users/andreas-ibm/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-04-18T15:51:33Z","updated_at":"2018-04-19T10:33:02Z","closed_at":null,"author_association":"NONE","body":"So after my previous issue, I now have a working OVS service  (thanks @bharnden, I tried just checking out the rel5.1 branch but it wouldn't start so I went back to master with manually applied patch).\r\n\r\nThe default config file has some (in my opinion) weaknesses:\r\n1. It doesn't really explain what it's doing\r\n2. It uses the old deprecated ifconfig\r\n3. It doesn't do anything useful by default (OK, you could probably argue otherwise, I simply couldn't see the value of creating veth pairs and routing to them.\r\n\r\nTo address 1 and 2 I've changed it so that it generates the following:\r\n```\r\n#!/bin/sh\r\n# auto-generated by OvsService (OvsService.py)\r\n## First make sure that the ovs services are up and running\r\n/etc/init.d/openvswitch-switch start < /dev/null\r\n\r\n## create the switch itself, set the fail mode to secure, \r\n## this stops it from routing traffic without defined flows.\r\n## remove the -- and everything after if you want it to act as a regular switch\r\novs-vsctl add-br ovsbr0 -- set Bridge ovsbr0 fail-mode=secure\r\n\r\n## Now add all our interfaces as ports to the switch\r\n## Create a veth pair to send the data to\r\nip link add rtr0 type veth peer name sw0\r\n## Add the CORE interface to the switch\r\novs-vsctl add-port ovsbr0 eth0 -- set Interface eth0 ofport_request=1\r\n## And then add its sibling veth interface\r\novs-vsctl add-port ovsbr0 sw0 -- set Interface sw0 ofport_request=2\r\n## start them up so we can send/receive data\r\novs-ofctl mod-port ovsbr0 eth0 up\r\novs-ofctl mod-port ovsbr0 sw0 up\r\n## Bring up the lower part of the veth pair\r\nip link set dev rtr0 up\r\n## Create a veth pair to send the data to\r\nip link add rtr1 type veth peer name sw1\r\n## Add the CORE interface to the switch\r\novs-vsctl add-port ovsbr0 eth1 -- set Interface eth1 ofport_request=3\r\n## And then add its sibling veth interface\r\novs-vsctl add-port ovsbr0 sw1 -- set Interface sw1 ofport_request=4\r\n## start them up so we can send/receive data\r\novs-ofctl mod-port ovsbr0 eth1 up\r\novs-ofctl mod-port ovsbr0 sw1 up\r\n## Bring up the lower part of the veth pair\r\nip link set dev rtr1 up\r\n\r\n## We assume there will be an SDN controller on the other end of this, \r\n## but it will still function if there's not\r\novs-vsctl set-controller ovsbr0 tcp:127.0.0.1:6633\r\n\r\n## Now to create some default flows, \r\n## if the above controller will be present then you probably want to delete them\r\n## Take the data from the CORE interface and put it on the veth and vice versa\r\novs-ofctl add-flow ovsbr0 priority=1000,in_port=1,action=output:2\r\novs-ofctl add-flow ovsbr0 priority=1000,in_port=2,action=output:1\r\n## Take the data from the CORE interface and put it on the veth and vice versa\r\novs-ofctl add-flow ovsbr0 priority=1000,in_port=3,action=output:4\r\novs-ofctl add-flow ovsbr0 priority=1000,in_port=4,action=output:3\r\n```\r\nSo I've added a bunch of comments explaining to the user what the script is doing, should help in their OVS education :-).\r\n\r\nI've set the fail-mode of the bridge to secure, this has the effect of not creating the default \"NORMAL\" rule that makes it act like a default switch (see better explanation here: http://docs.openvswitch.org/en/latest/tutorials/ovs-advanced/) I could be convinced that this is a Bad Thing, but at the moment I believe that the use of the OVS service in CORE should have secure fail mode.\r\n\r\nI've set it to explicitly set the port numbers of the interfaces, this makes no functional change (i.e. the numbers happen to be what OVS would have chosen), but it makes it clear when you write the flows which ports it is flowing between.\r\n\r\nI've changed it to use the ovs-ofctl mod-port command to bring the interfaces up (and a ip link command for the veth peer not under ovs control) to avoid ifconfig.\r\n\r\nHere's the change, I can do a PR if that's preferrable\r\n```\r\ndiff --git a/daemon/core/services/sdn.py b/daemon/core/services/sdn.py\r\nindex 63ca610..6271d09 100644\r\n--- a/daemon/core/services/sdn.py\r\n+++ b/daemon/core/services/sdn.py\r\n@@ -51,10 +51,15 @@ class OvsService(SdnService):\r\n\r\n         cfg = \"#!/bin/sh\\n\"\r\n         cfg += \"# auto-generated by OvsService (OvsService.py)\\n\"\r\n-        cfg += \"/etc/init.d/openvswitch-switch start < /dev/null\\n\"\r\n-        cfg += \"ovs-vsctl add-br ovsbr0\\n\"\r\n-        cfg += \"ifconfig ovsbr0 up\\n\"\r\n-\r\n+        cfg += \"## First make sure that the ovs services are up and running\\n\"\r\n+        cfg += \"/etc/init.d/openvswitch-switch start < /dev/null\\n\\n\"\r\n+        cfg += \"## create the switch itself, set the fail mode to secure, \\n\"\r\n+        cfg += \"## this stops it from routing traffic without defined flows.\\n\"\r\n+        cfg += \"## remove the -- and everything after if you want it to act as a regular switch\\n\"\r\n+        cfg += \"ovs-vsctl add-br ovsbr0 -- set Bridge ovsbr0 fail-mode=secure\\n\"\r\n+\r\n+        cfg += \"\\n## Now add all our interfaces as ports to the switch\\n\"\r\n+        portnum = 1\r\n         for ifc in node.netifs():\r\n             if hasattr(ifc, 'control') and ifc.control is True:\r\n                 continue\r\n@@ -62,9 +67,10 @@ class OvsService(SdnService):\r\n             ifnum = ifnumstr[0]\r\n\r\n             # create virtual interfaces\r\n+            cfg += \"## Create a veth pair to send the data to\\n\"\r\n             cfg += \"ip link add rtr%s type veth peer name sw%s\\n\" % (ifnum, ifnum)\r\n-            cfg += \"ifconfig rtr%s up\\n\" % ifnum\r\n-            cfg += \"ifconfig sw%s up\\n\" % ifnum\r\n+#            cfg += \"ifconfig rtr%s up\\n\" % ifnum\r\n+#            cfg += \"ifconfig sw%s up\\n\" % ifnum\r\n\r\n             # remove ip address of eths because quagga/zebra will assign same IPs to rtr interfaces\r\n             # or assign them manually to rtr interfaces if zebra is not running\r\n@@ -81,17 +87,31 @@ class OvsService(SdnService):\r\n                     raise ValueError(\"invalid address: %s\" % ifcaddr)\r\n\r\n             # add interfaces to bridge\r\n-            cfg += \"ovs-vsctl add-port ovsbr0 eth%s\\n\" % ifnum\r\n-            cfg += \"ovs-vsctl add-port ovsbr0 sw%s\\n\" % ifnum\r\n+            # Make port numbers explicit so they're easier to follow in reading the script\r\n+            cfg += \"## Add the CORE interface to the switch\\n\"\r\n+            cfg += \"ovs-vsctl add-port ovsbr0 eth%s -- set Interface eth%s ofport_request=%d\\n\" % (ifnum, ifnum, portnum)\r\n+            cfg += \"## And then add its sibling veth interface\\n\"\r\n+            cfg += \"ovs-vsctl add-port ovsbr0 sw%s -- set Interface sw%s ofport_request=%d\\n\" % (ifnum, ifnum, portnum+1)\r\n+            cfg += \"## start them up so we can send/receive data\\n\"\r\n+            cfg += \"ovs-ofctl mod-port ovsbr0 eth%s up\\n\" % ifnum\r\n+            cfg += \"ovs-ofctl mod-port ovsbr0 sw%s up\\n\" % ifnum\r\n+            cfg += \"## Bring up the lower part of the veth pair\\n\"\r\n+            cfg += \"ip link set dev rtr%s up\\n\" % ifnum\r\n+            portnum += 2\r\n\r\n         # Add rule for default controller if there is one local (even if the controller is not local, it finds it)\r\n+        cfg += \"\\n## We assume there will be an SDN controller on the other end of this, \\n\"\r\n+        cfg += \"## but it will still function if there's not\\n\"\r\n         cfg += \"ovs-vsctl set-controller ovsbr0 tcp:127.0.0.1:6633\\n\"\r\n\r\n+        cfg += \"\\n## Now to create some default flows, \\n\"\r\n+        cfg += \"## if the above controller will be present then you probably want to delete them\\n\"\r\n         # Setup default flows\r\n         portnum = 1\r\n         for ifc in node.netifs():\r\n             if hasattr(ifc, 'control') and ifc.control is True:\r\n                 continue\r\n+            cfg += \"## Take the data from the CORE interface and put it on the veth and vice versa\\n\"\r\n             cfg += \"ovs-ofctl add-flow ovsbr0 priority=1000,in_port=%d,action=output:%d\\n\" % (portnum, portnum + 1)\r\n             cfg += \"ovs-ofctl add-flow ovsbr0 priority=1000,in_port=%d,action=output:%d\\n\" % (portnum + 1, portnum)\r\n             portnum += 2\r\n```\r\n\r\nFor point 3 I'll put that in a separate comment..."},"comment":{"url":"https://api.github.com/repos/coreemu/core/issues/comments/382688347","html_url":"https://github.com/coreemu/core/issues/150#issuecomment-382688347","issue_url":"https://api.github.com/repos/coreemu/core/issues/150","id":382688347,"user":{"login":"andreas-ibm","id":18004999,"avatar_url":"https://avatars2.githubusercontent.com/u/18004999?v=4","gravatar_id":"","url":"https://api.github.com/users/andreas-ibm","html_url":"https://github.com/andreas-ibm","followers_url":"https://api.github.com/users/andreas-ibm/followers","following_url":"https://api.github.com/users/andreas-ibm/following{/other_user}","gists_url":"https://api.github.com/users/andreas-ibm/gists{/gist_id}","starred_url":"https://api.github.com/users/andreas-ibm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andreas-ibm/subscriptions","organizations_url":"https://api.github.com/users/andreas-ibm/orgs","repos_url":"https://api.github.com/users/andreas-ibm/repos","events_url":"https://api.github.com/users/andreas-ibm/events{/privacy}","received_events_url":"https://api.github.com/users/andreas-ibm/received_events","type":"User","site_admin":false},"created_at":"2018-04-19T10:33:02Z","updated_at":"2018-04-19T10:33:02Z","author_association":"NONE","body":"I have EMANE (and was using it with CORE 4.8.1), so that wasn't the issue, I'll switch back to the 5.1 branch later if you want an issue on it?\r\n\r\nI'm quite happy with the current generic LinuxBridge default, they're quick and easy and work, I specifically added an OVS switch for my current needs that I couldn't address with LinuxBridge\r\n\r\nI want an transparent packet marking tool, so my current OvsService config looks like this:\r\n```\r\n#!/bin/sh\r\n# auto-generated by OvsService (OvsService.py)\r\n## First make sure that the ovs services are up and running\r\n/etc/init.d/openvswitch-switch start < /dev/null\r\n\r\n## create the switch itself, set the fail mode to secure, \r\n## this stops it from routing traffic without defined flows.\r\n## remove the -- and everything after if you want it to act as a regular switch\r\novs-vsctl add-br ovsbr0 -- set Bridge ovsbr0 fail-mode=secure\r\n\r\n## Now add all our interfaces as ports to the switch\r\n## Add the CORE interface to the switch\r\novs-vsctl add-port ovsbr0 eth0 -- set Interface eth0 ofport_request=1\r\n## start them up so we can send/receive data\r\novs-ofctl mod-port ovsbr0 eth0 up\r\n\r\n## Add the CORE interface to the switch\r\novs-vsctl add-port ovsbr0 eth1 -- set Interface eth1 ofport_request=2\r\n## start them up so we can send/receive data\r\novs-ofctl mod-port ovsbr0 eth1 up\r\n\r\n## We assume there will be an SDN controller on the other end of this, \r\n## but it will still function if there's not\r\novs-vsctl set-controller ovsbr0 tcp:127.0.0.1:6633\r\n\r\n## Now to create some default flows, \r\n## if the above controller will be present then you probably want to delete them\r\novs-ofctl add-flows ovsbr0 - <<'EOF'\r\ntable=0, priority=0 actions=resubmit(,1)\r\ntable=1, priority=99,in_port=1 actions=resubmit(,2)\r\ntable=1, priority=99,in_port=2 actions=resubmit(,2)\r\ntable=1, priority=0 actions=drop\r\ntable=2, priority=99,in_port=2 actions=output:1\r\ntable=2, priority=10,in_port=1 actions=mod_nw_tos:12,2\r\ntable=2, priority=99,icmp,in_port=1 actions=mod_nw_tos:184,2\r\ntable=2, priority=99,arp,in_port=1 actions=output:2\r\ntable=2, priority=99,udp,in_port=1,tp_dst=5269 actions=mod_nw_tos:88,2\r\ntable=2, priority=99,tcp,in_port=1,tp_dst=5269 actions=mod_nw_tos:88,2\r\nEOF\r\n```\r\n\r\nSo I don't want any additional ports on top of the ones I've defined in CORE, I just want OVS to do some intelligent switching (in addition I'm dropping types of traffic I haven't marked, I'll be extending this with more flows over the next few days / weeks). And yes, I'm getting to the point where I should be defining my own SDN controller rather than hand-cranking the flows!\r\n\r\nMy thoughts were if we start with the service having content along the lines of what's in the OVS Advanced Features tutorial (http://docs.openvswitch.org/en/latest/tutorials/ovs-advanced/) then it'll be easier for users to get up to speed with it."}}
{"actor":{"display_login":"andreas-ibm"}}