-
Notifications
You must be signed in to change notification settings - Fork 51
NetKAT JSON Syntax
The NetKAT JSON syntax is used underneath the covers for the http-controller
subcommand. The Frenetic Python library translates Python objects to REST/JSON calls to Frenetic. You can use REST/JSON from any other programming language to create your own bindings.
This syntax has the following benefits:
- It's usable by any programming language that speaks REST and JSON
- You can write dynamic programs with whatever native language constructs you feel comfortable with. Then simply convert them to JSON and REST to make Frenetic do the hard work.
And the following limitations:
- JSON can be verbose
Only the NetKAT Syntax is presented here. See here for details on REST URL's in which to use these JSON objects.
A predicate is a boolean condition for matching packets. It's generally used in filter
and IfThenElse
policies,
outlined in the next section.
Predicate | Matches Packets With... |
---|---|
{"type":"false"} |
matches no packets |
("type":"true"} |
matches all packets |
In JSON, the predicate looks like:
{ "type": "test", "header": "ethdst", "value": 12384671234 }
Values are generally strings or integers. The exception are ip4src
and ip4dst
which can be a single host or a network with a mask
{ "type": "test", "header": "ip4src", "value": {"addr":"192.168.56.123"} }
{ "type": "test", "header": "ip4src", "value": {"addr":"192.168.56.0", "mask":24} }
... and Location, which can reference a physical port:
{ "type": "test", "header": "location", "value": {"type":"physical", "port": 1} }
Header | Matches Packets With... |
---|---|
ethdst |
Ethernet destination address: most common format is 6-byte colon-separated hex |
ethsrc |
Ethernet source address |
ethtype |
Ethernet type. For VLAN packets, this is the type of the inner packet, per OpenFlow 1.0 |
ip4dst |
IPv4 desintation address: see above for formats |
ip4src |
IPv4 source address |
ipproto |
IPv4 protocol number or ARP opcode. Must be decimal and fit in 16 bits. |
location |
Ingress port number. See above for format. Must be less than 65520 |
switch |
Ingress switch datapath ID. |
tcpsrcport |
TCP/UDP source port |
tcpdstport |
TCP/UDP destination port. |
vlan |
VLAN id. |
vlanpcp |
VLAN PCP. priority code point. |
Predicate | Matches Packets With... |
---|---|
{"type":"not", "pred": ... } |
the given predicate not matching |
{"type":"and", "preds": [...] } |
all predicates matching |
{"type":"or", "preds": [...] } |
one or more predicates matching |
A NetKAT policy directs the switch to perform an action on a packet.
Policy | Does This With a Packet... |
---|---|
{"type":"filter", "pred":...} |
Accepts all packets that meet the predicate. Drops any other packets |
Note that in a filter you can use the predicate {"type":"false"}
to drop all packets or {"type":"true"}
to accept all packets.
The format for setting a header is:
{ "type": "mod", "header": "ethdst", "value": 12384671234 }
And the header names are exactly those listed above in Field Match Primitives. The exceptions are:
-
switch
cannot be used as a header -
ip4src
andip4dst
only accept a host without a net mask
In addition, there are several options for setting the location.
{ "type": "mod", "header": "location", "value": {"type":"physical", "port": 1} }
{ "type": "mod", "header": "location", "value": {"type":"query", "name": "tag"} }
{ "type": "mod", "header": "location", "value": {"type":"pipe", "name": "tag"} }
The first of these sends a packet to an egress port, the second to a statistics query bucket, the third to a controller. Note that a packet may only go to ONE of these destinations ... to send copies to more than on destination, use a Union combination.
Policy | Does This With a Packet... |
---|---|
{"type":"seq", "pols":[...]} |
Executes policies in sequence. |
{"type":"union", "pols":[...]} |
Makes virtual copies of the packet and simultaneously executes all policies |
Note there is no if-then-else
construct, but you can construct it using the other combinations like this:
{ "type":"union", "pols":[
{ "type": "seq", "pols": [
{ "type": "filter", "pred": predicate },
TruePolicy
]},
{ "type": "seq", "pols": [
{ "type": "filter", "pred": {
{"type": "not", "pred": predicate }
},
FalsePolicy
]}
]}
{
"pols": [
{
"pols": [
{
"pred": {
"header": "switch",
"type": "test",
"value": "1"
},
"type": "filter"
},
{
"pols": [
{
"pols": [
{
"pred": {
"header": "ethsrc",
"type": "test",
"value": "00:00:00:00:00:01"
},
"type": "filter"
},
{
"header": "location",
"type": "mod",
"value": {
"type": "physical",
"port": 1
}
}
],
"type": "seq"
},
{
"pols": [
{
"pred": {
"pred": {
"header": "ethsrc",
"type": "test",
"value": "00:00:00:00:00:01"
},
"type": "neg"
},
"type": "filter"
},
{
"pols": [
{
"pols": [
{
"pred": {
"header": "ethsrc",
"type": "test",
"value": "00:00:00:00:00:02"
},
"type": "filter"
},
{
"header": "location",
"type": "mod",
"value": {
"type": "physical",
"port": 2
}
}
],
"type": "seq"
},
{
"pols": [
{
"pred": {
"pred": {
"header": "ethsrc",
"type": "test",
"value": "00:00:00:00:00:02"
},
"type": "neg"
},
"type": "filter"
},
{
"pols": [
{
"pols": [
{
"pred": {
"header": "ethsrc",
"type": "test",
"value": "00:00:00:00:00:03"
},
"type": "filter"
},
{
"header": "location",
"type": "mod",
"value": {
"type": "physical",
"port": 3
}
}
],
"type": "seq"
},
{
"pols": [
{
"pred": {
"pred": {
"header": "ethsrc",
"type": "test",
"value": "00:00:00:00:00:03"
},
"type": "neg"
},
"type": "filter"
},
{
"header": "location",
"type": "mod",
"value": {
"type": "physical",
"port": 4
}
}
],
"type": "seq"
}
],
"type": "union"
}
],
"type": "seq"
}
],
"type": "union"
}
],
"type": "seq"
}
],
"type": "union"
}
],
"type": "seq"
},
{
"pols": [
{
"pred": {
"header": "switch",
"type": "test",
"value": "2"
},
"type": "filter"
},
{
"pols": [
{
"pols": [
{
"pols": [
{
"pred": {
"preds": [
{
"header": "ethtype",
"type": "test",
"value": 2048
},
{
"header": "ip4src",
"type": "test",
"value": {
"mask": 32,
"addr": "192.168.0.1"
}
}
],
"type": "and"
},
"type": "filter"
},
{
"header": "location",
"type": "mod",
"value": {
"type": "physical",
"port": 1
}
}
],
"type": "seq"
},
{
"pols": [
{
"pred": {
"preds": [
{
"header": "ethtype",
"type": "test",
"value": 2048
},
{
"header": "ip4src",
"type": "test",
"value": {
"mask": 32,
"addr": "192.168.0.2"
}
}
],
"type": "and"
},
"type": "filter"
},
{
"header": "location",
"type": "mod",
"value": {
"type": "physical",
"port": 2
}
}
],
"type": "seq"
}
],
"type": "union"
},
{
"pols": [
{
"pred": {
"preds": [
{
"header": "ethtype",
"type": "test",
"value": 2048
},
{
"header": "ip4src",
"type": "test",
"value": {
"mask": 32,
"addr": "192.168.0.3"
}
}
],
"type": "and"
},
"type": "filter"
},
{
"header": "location",
"type": "mod",
"value": {
"type": "physical",
"port": 3
}
}
],
"type": "seq"
}
],
"type": "union"
}
],
"type": "seq"
}
],
"type": "union"
}