Skip to content

Instantly share code, notes, and snippets.

@s-geissler
Created November 28, 2016 09:48
Show Gist options
  • Save s-geissler/084074718eca1e9d71a68d3833835177 to your computer and use it in GitHub Desktop.
Save s-geissler/084074718eca1e9d71a68d3833835177 to your computer and use it in GitHub Desktop.
NEC Multitable Processing
from ryu.base import app_manager
from ryu.controller import dpset
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.ofproto import ether
from ryu.lib.packet import packet, ethernet
from ryu.lib import mac
from time import sleep
class MPLS(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
NEC_TABLE_NORMAL1 = 0
NEC_TABLE_EXPANDED = 1
NEC_TABLE_NORMAL2 = 20
NEC_TABLE_MPLS1 = 50
NEC_TABLE_MPLS2 = 51
NEC_TABLE_SOFTWARE = 99
NEC_TABLE_DICT = [NEC_TABLE_NORMAL1, NEC_TABLE_EXPANDED, NEC_TABLE_NORMAL2, NEC_TABLE_MPLS1,
NEC_TABLE_MPLS2, NEC_TABLE_SOFTWARE]
OVS_TABLE_MPLS1 = 0
OVS_TABLE_MPLS2 = 1
def __init__(self, *args, **kwargs):
super(MPLS, self).__init__(*args, **kwargs)
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
# If you hit this you might want to increase
# the "miss_send_length" of your switch
if ev.msg.msg_len < ev.msg.total_len:
self.logger.debug("packet truncated: only %s of %s bytes",
ev.msg.msg_len, ev.msg.total_len)
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]
self.logger.info("packet in dpid:%s port:%s table:%s %s->%s -- %s", datapath.id, in_port, msg.table_id, eth.src, eth.dst, pkt)
@set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
def handler_datapath(self, ev):
if ev.enter:
sleep(1)
if ev.dp.id == 0x000158c232e8b2be:
self.logger.info("Connection by NEC PF5240")
self._nec_pf5240_connect(ev)
else:
self.logger.warn("Connection by unknown dpid %s", ev.dp.id)
def _nec_pf5240_connect(self, ev):
log_prefix = "pf5240"
datapath = ev.dp
parser = datapath.ofproto_parser
# Delete all present flow entries
self._empty_all_tables(datapath)
field_label = parser.OFPMatchField.make(datapath.ofproto.OXM_OF_MPLS_LABEL, 80)
field_bos = parser.OFPMatchField.make(datapath.ofproto.OXM_OF_MPLS_BOS, 1)
field_eth_src = parser.OFPMatchField.make(datapath.ofproto.OXM_OF_ETH_SRC, mac.haddr_to_bin('00:00:01:00:00:01'))
field_eth_dst = parser.OFPMatchField.make(datapath.ofproto.OXM_OF_ETH_DST, mac.haddr_to_bin('00:00:01:00:00:02'))
mod_normal1 = parser.OFPFlowMod(datapath=datapath,
priority=65000, # Priority
table_id=self.NEC_TABLE_NORMAL1, # Push rule tu table NORMAL1
match=parser.OFPMatch( # Match on
eth_type=ether.ETH_TYPE_IP, # Ethertype IP
),
instructions=[
#parser.OFPInstructionActions(
# datapath.ofproto.OFPIT_APPLY_ACTIONS,
# [
#parser.OFPActionSetField(field_eth_src), # Set source
# parser.OFPActionSetField(field_eth_dst), # and dst MAC
# parser.OFPActionOutput(3),
# ]
#),
#parser.OFPInstructionWriteMetadata(0, 0),
parser.OFPInstructionGotoTable(self.NEC_TABLE_NORMAL2),
],
)
datapath.send_msg(mod_normal1)
sleep(0.5)
self.logger.warn("%s --- done pushing flowmod to table normal1", log_prefix)
def _empty_all_tables(self, datapath):
for table in self.NEC_TABLE_DICT:
self._empty_table(datapath, table)
def _empty_table(self, datapath, table_id):
self.logger.warn(" --- deleting flow entries in table %s", table_id)
datapath.send_msg(
datapath.ofproto_parser.OFPFlowMod(
datapath,
0,
0,
table_id,
datapath.ofproto.OFPFC_DELETE,
0,
0,
1,
datapath.ofproto.OFPCML_NO_BUFFER,
datapath.ofproto.OFPP_ANY,
datapath.ofproto.OFPG_ANY,
0,
datapath.ofproto_parser.OFPMatch(),
[]
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment