I am working on implemanting mpls in ryu, I have written the app using openflow actions: Push Mpls; Pop.. But I don't know why somehow I am getting only 1/2 of ping when pinging.
As I am working in a looped topology, I used networkx in order to get the out port through which the packets will be forwarded.
def push_mpls(self, ev, out_port):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
dpid = format(datapath.id, "d").zfill(16)
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]
dst = eth.dst
src = eth.src
ethtype = eth.ethertype
ip_header= ipv4.ipv4(dst='10.0.0.2', src='10.0.0.1')
match = parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_type=ethtype)
self.label = self.label + 1
self.logger.info("Flow actions: push MPLS=%s, out_port=%s, dst=%s, dpid=%s ", self.label, out_port, dst, dpid)
pkt_mpls= packet.Packet()
pkt_mpls.add_protocol(ethernet.ethernet(ethertype=ether_types.ETH_TYPE_MPLS,
dst=eth.dst,src= eth.src))
pkt_mpls.add_protocol(mpls.mpls(label= self.label ))
pkt_mpls.add_protocol(ip_header)
pkt_mpls.serialize()
data=msg.data
#actions = [parser.OFPActionOutput(out_port)]
actions = [ parser.OFPActionPushMpls(ethertype=ether_types.ETH_TYPE_MPLS ),parser.OFPActionSetField(mpls_label=self.label),parser.OFPActionOutput(3)]
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,in_port=in_port, actions=actions,data=data)
datapath.send_msg(out)
self.add_flow(datapath, 1, match, actions)
def swap_mpls(self, ev, out_port):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
dpid = format(datapath.id, "d").zfill(16)
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]
dst = eth.dst
src = eth.src
ethtype = eth.ethertype
ip_header= ipv4.ipv4(dst='10.0.0.2', src='10.0.0.1')
mpls_proto = pkt.get_protocol(mpls.mpls)
match = parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_type=ethtype, mpls_label=mpls_proto.label )
self.label = self.label + 1
self.logger.info("Flow actions: swap MPLS=%s, out_port=%s, dst=%s, dpid=%s", self.label, out_port, dst, dpid)
pkt_mpls= packet.Packet()
pkt_mpls.add_protocol(ethernet.ethernet(ethertype=ether_types.ETH_TYPE_MPLS,
dst=eth.dst,src= eth.src))
pkt_mpls.add_protocol(mpls.mpls(label= self.label))
pkt_mpls.add_protocol(ip_header)
pkt_mpls.serialize()
data=msg.data
#actions = [parser.OFPActionOutput(2)]
actions = [parser.OFPActionPopMpls(), parser.OFPActionPushMpls(ethertype=ether_types.ETH_TYPE_MPLS),parser.OFPActionSetField(mpls_label=self.label), parser.OFPActionOutput(2)]
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,in_port=in_port, actions=actions, data= msg.data)
datapath.send_msg(out)
self.add_flow(datapath, 1, match, actions)
def pop_mpls(self, ev, out_port):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
dpid = format(datapath.id, "d").zfill(16)
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]
dst = eth.dst
src = eth.src
ethtype = eth.ethertype
ip_header= ipv4.ipv4(dst='10.0.0.2', src='10.0.0.1')
mpls_proto = pkt.get_protocol(mpls.mpls)
if mpls_proto is not None:
mpls_label=mpls_proto.label
match = parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_type=ethtype, mpls_label=mpls_proto.label )
else:
match = parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_type=ethtype)
self.logger.info("Flow actions: Pop MPLS=%s, out_port=%s, dst=%s , dpid=%s", self.label, out_port, dst, dpid)
data = msg.data
#actions = [parser.OFPActionOutput(3)]
actions = [parser.OFPActionPopMpls(),parser.OFPActionOutput(3)]
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,in_port=in_port, actions=actions, data=data)
datapath.send_msg(out)
self.add_flow(datapath, 1, match, actions)
//Path function
def get_path(self, ev):
msg = ev.msg
datapath = msg.datapath
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]
dst = eth.dst
src = eth.src
dpid = format(datapath.id, "d").zfill(16)
self.net=nx.DiGraph()
if src not in self.net: #Learn it
self.net.add_node(src) # Add a node to the graph
self.net.add_edge(src,dpid) # Add a link from the node to it's edge switch
self.net.add_edge(dpid,src,port=msg.match['in_port']) # Add link from switch to node and make sure you are identifying the output port.
if dst in self.net:
path=nx.shortest_path(self.net,src,dst) # get shortest path
next=path[path.index(dpid)+1] #get next hop
out_port=self.net[dpid][next]['port'] #get output port
print ('---the path is :----')
print (path)
return out_port
return None
///Packet In
@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]
if eth.ethertype == ether_types.ETH_TYPE_LLDP:
# ignore lldp packet
return
if eth.ethertype == ether_types.ETH_TYPE_IPV6:
return
dst = eth.dst
src = eth.src
ethtype = eth.ethertype
dpid = format(datapath.id, "d").zfill(16)
self.mac_to_port.setdefault(dpid, {})
mpls_proto = pkt.get_protocol(mpls.mpls)
out_port = self.get_path(ev)
if out_port is not None:
out_port = out_port
else:
out_port = ofproto.OFPP_FLOOD
if ethtype == ether_types.ETH_TYPE_IP and dpid == "0000000000000001":
self.push_mpls(ev, out_port)
if ethtype ==ether_types.ETH_TYPE_MPLS and dpid == "0000000000000003":
self.swap_mpls(ev, out_port)
if ethtype ==ether_types.ETH_TYPE_MPLS and dpid == "0000000000000002":
self.swap_mpls(ev, out_port)
if ethtype ==ether_types.ETH_TYPE_MPLS and dpid == "0000000000000004":
self.pop_mpls(ev, out_port)
data = msg.data
actions = [parser.OFPActionOutput(out_port)]
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,in_port=in_port, actions=actions, data=data)
datapath.send_msg(out)