9#include "ns3/tcp-l4-protocol.h" 
   10#include "ns3/udp-l4-protocol.h" 
   27    uint8_t ea[ETH_ADDR_LEN];
 
   29    return eth_addr_to_uint64(ea);
 
 
   35    return "The ns-3 team";
 
 
   47    return "Simulated OpenFlow Switch";
 
 
   60        TypeId(
"ns3::OpenFlowSwitchNetDevice")
 
   62            .SetGroupName(
"Openflow")
 
   65                          "The identification of the OpenFlowSwitchNetDevice/Datapath, needed for " 
   66                          "OpenFlow compatibility.",
 
   70            .AddAttribute(
"FlowTableLookupDelay",
 
   71                          "A real switch will have an overhead for looking up in the flow table. " 
   72                          "For the default, we simulate a standard TCAM on an FPGA.",
 
   76            .AddAttribute(
"Flags", 
 
   78                          "Flags to turn different functionality on/off, such as whether to inform " 
   79                          "the controller when a flow expires, or how to handle fragments.",
 
   84            .AddAttribute(
"FlowTableMissSendLength", 
 
   86                          "When forwarding a packet the switch didn't match up to the controller, " 
   87                          "it can be more efficient to forward only the first x bytes.",
 
 
  112        NS_LOG_ERROR(
"Not enough memory to create the flow table.");
 
 
  165        NS_FATAL_ERROR(
"Device does not support eui 48 addresses: cannot be added to switch.");
 
  167    if (!switchPort->SupportsSendFrom())
 
  169        NS_FATAL_ERROR(
"Device does not support SendFrom: cannot be added to switch.");
 
  176    if (
m_ports.size() < DP_MAX_PORTS)
 
  186        NS_LOG_DEBUG(
"RegisterProtocolHandler for " << switchPort->GetInstanceTypeId().GetName());
 
  192        m_channel->AddChannel(switchPort->GetChannel());
 
 
  314    if (out_port != OFPP_CONTROLLER)
 
  316        OutputPort(packet_uid, in_port, out_port, ignore_no_fwd);
 
 
  335                                  uint16_t protocolNumber)
 
  343    data.packet = packet;
 
  344    data.buffer = buffer;
 
  345    data.protocolNumber = protocolNumber;
 
 
  408    size_t actions_len = ntohs(ovpm->header.length) - 
sizeof *ovpm;
 
  409    unsigned int vport = ntohl(ovpm->vport);
 
  410    unsigned int parent_port = ntohl(ovpm->parent_port);
 
  413    vport_table_entry* vpe = vport_table_lookup(&
m_vportTable, vport);
 
  417        SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
 
  423    if (v_code != ACT_VALIDATION_OK)
 
  425        SendErrorMsg(OFPET_BAD_ACTION, v_code, ovpm, ntohs(ovpm->header.length));
 
  429    vpe = vport_table_entry_alloc(actions_len);
 
  432    vpe->parent_port = parent_port;
 
  433    if (vport < OFPP_VP_START || vport > OFPP_VP_END)
 
  435        NS_LOG_ERROR(
"port " << vport << 
" is not in the virtual port range (" << OFPP_VP_START
 
  436                             << 
"-" << OFPP_VP_END << 
")");
 
  437        SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
 
  438        free_vport_table_entry(vpe); 
 
  442    vpe->port_acts->actions_len = actions_len;
 
  443    memcpy(vpe->port_acts->actions, ovpm->actions, actions_len);
 
  445    int error = insert_vport_table_entry(&
m_vportTable, vpe);
 
  448        NS_LOG_ERROR(
"could not insert port table entry for port " << vport);
 
 
  461    NS_LOG_INFO(
"Creating Openflow buffer from packet.");
 
  469    const int headroom = 128 + 2;
 
  470    const int hard_header = VLAN_ETH_HEADER_LEN;
 
  471    ofpbuf* buffer = ofpbuf_new(headroom + hard_header + mtu);
 
  472    buffer->data = (
char*)buffer->data + headroom + hard_header;
 
  479    buffer->l2 = 
new eth_header;
 
  480    eth_header* eth_h = (eth_header*)buffer->l2;
 
  481    dst.
CopyTo(eth_h->eth_dst); 
 
  482    src.
CopyTo(eth_h->eth_src); 
 
  485        eth_h->eth_type = htons(ETH_TYPE_ARP); 
 
  489        eth_h->eth_type = htons(ETH_TYPE_IP); 
 
  497    l2_length = ETH_HEADER_LEN;
 
  504        if (packet->PeekHeader(ip_hd))
 
  506            buffer->l3 = 
new ip_header;
 
  507            ip_header* ip_h = (ip_header*)buffer->l3;
 
  508            ip_h->ip_ihl_ver = IP_IHL_VER(5, IP_VERSION); 
 
  509            ip_h->ip_tos = ip_hd.
GetTos();                
 
  510            ip_h->ip_tot_len = packet->GetSize();         
 
  513            ip_h->ip_ttl = ip_hd.
GetTtl();                      
 
  517            ip_h->ip_csum = csum(&ip_h, 
sizeof ip_h);           
 
  519            packet->RemoveHeader(ip_hd);
 
  521            l3_length = IP_HEADER_LEN;
 
  529        if (packet->PeekHeader(arp_hd))
 
  531            buffer->l3 = 
new arp_eth_header;
 
  532            arp_eth_header* arp_h = (arp_eth_header*)buffer->l3;
 
  533            arp_h->ar_hrd = ARP_HRD_ETHERNET; 
 
  534            arp_h->ar_pro = ARP_PRO_IP;       
 
  535            arp_h->ar_op = arp_hd.
m_type;     
 
  541            arp_h->ar_hln = 
sizeof arp_h->ar_tha;                     
 
  542            arp_h->ar_pln = 
sizeof arp_h->ar_tpa;                     
 
  544            packet->RemoveHeader(arp_hd);
 
  546            l3_length = ARP_ETH_HEADER_LEN;
 
  552        ip_header* ip_h = (ip_header*)buffer->l3;
 
  556            if (packet->PeekHeader(tcp_hd))
 
  558                buffer->l4 = 
new tcp_header;
 
  559                tcp_header* tcp_h = (tcp_header*)buffer->l4;
 
  564                tcp_h->tcp_ctl = TCP_FLAGS(tcp_hd.
GetFlags()); 
 
  567                tcp_h->tcp_csum = csum(&tcp_h, 
sizeof tcp_h);  
 
  569                packet->RemoveHeader(tcp_hd);
 
  571                l4_length = TCP_HEADER_LEN;
 
  577            if (packet->PeekHeader(udp_hd))
 
  579                buffer->l4 = 
new udp_header;
 
  580                udp_header* udp_h = (udp_header*)buffer->l4;
 
  583                udp_h->udp_len = htons(UDP_HEADER_LEN + packet->GetSize());
 
  585                ip_header* ip_h = (ip_header*)buffer->l3;
 
  586                uint32_t udp_csum = csum_add32(0, ip_h->ip_src);
 
  587                udp_csum = csum_add32(udp_csum, ip_h->ip_dst);
 
  588                udp_csum = csum_add16(udp_csum, IP_TYPE_UDP << 8);
 
  589                udp_csum = csum_add16(udp_csum, udp_h->udp_len);
 
  590                udp_csum = csum_continue(udp_csum, udp_h, 
sizeof udp_h);
 
  591                udp_h->udp_csum = csum_finish(
 
  592                    csum_continue(udp_csum, buffer->data, buffer->size)); 
 
  594                packet->RemoveHeader(udp_hd);
 
  596                l4_length = UDP_HEADER_LEN;
 
  602    packet->CopyData((uint8_t*)buffer->data, packet->GetSize());
 
  606        ofpbuf_push(buffer, buffer->l4, l4_length);
 
  607        delete (tcp_header*)buffer->l4;
 
  611        ofpbuf_push(buffer, buffer->l3, l3_length);
 
  612        delete (ip_header*)buffer->l3;
 
  616        ofpbuf_push(buffer, buffer->l2, l2_length);
 
  617        delete (eth_header*)buffer->l2;
 
 
  632    NS_LOG_INFO(
"--------------------------------------------");
 
  644    for (
size_t i = 0; i < 
m_ports.size(); i++)
 
  646        if (
m_ports[i].netdev == netdev)
 
  667                    data.packet = packet->Copy();
 
  672                    m_ports[i].rx_bytes += buffer->size;
 
  673                    data.buffer = buffer;
 
  676                    data.protocolNumber = protocol;
 
  695        for (
size_t i = 0; i < 
m_ports.size(); i++)
 
  704        List deleted = LIST_INITIALIZER(&deleted);
 
  707        chain_timeout(
m_chain, &deleted);
 
  708        LIST_FOR_EACH_SAFE(f, n, sw_flow, node, &deleted)
 
  710            std::ostringstream str;
 
  712            for (
int i = 0; i < 6; i++)
 
  714                str << (i != 0 ? 
":" : 
"") << std::hex << f->key.flow.dl_src[i] / 16
 
  715                    << f->key.flow.dl_src[i] % 16;
 
  718            for (
int i = 0; i < 6; i++)
 
  720                str << (i != 0 ? 
":" : 
"") << std::hex << f->key.flow.dl_dst[i] / 16
 
  721                    << f->key.flow.dl_dst[i] % 16;
 
  727            list_remove(&f->node);
 
 
  742    for (
size_t i = 0; i < 
m_ports.size(); i++)
 
  744        if (i == (
unsigned)in_port) 
 
  748        if (flood && 
m_ports[i].config & OFPPC_NO_FLOOD) 
 
  754            OutputPort(packet_uid, in_port, prev_port, 
false);
 
  760        OutputPort(packet_uid, in_port, prev_port, 
false);
 
 
  769    if (out_port >= 0 && out_port < DP_MAX_PORTS)
 
  775            size_t bufsize = 
data.buffer->size;
 
  776            NS_LOG_INFO(
"Sending packet " << 
data.packet->GetUid() << 
" over port " << out_port);
 
 
  801    if (out_port == OFPP_FLOOD)
 
  805    else if (out_port == OFPP_ALL)
 
  809    else if (out_port == OFPP_CONTROLLER)
 
  813    else if (out_port == OFPP_IN_PORT)
 
  817    else if (out_port == OFPP_TABLE)
 
  821    else if (out_port >= OFPP_VP_START && out_port <= OFPP_VP_END)
 
  824        NS_LOG_INFO(
"packet sent to virtual port " << out_port);
 
  825        if (in_port < DP_MAX_PORTS)
 
  834    else if (in_port == out_port)
 
 
  847    return make_openflow_xid(openflow_len, type, 0, bufferp);
 
 
  855        update_openflow_length(buffer);
 
 
  867    ofpbuf* buffer = 
m_packetData.find(packet_uid)->second.buffer;
 
  868    size_t total_len = buffer->size;
 
  869    if (packet_uid != std::numeric_limits<uint32_t>::max() && max_len != 0 &&
 
  870        buffer->size > max_len)
 
  872        buffer->size = max_len;
 
  875    ofp_packet_in* opi = (ofp_packet_in*)ofpbuf_push_uninit(buffer, offsetof(ofp_packet_in, 
data));
 
  876    opi->header.version = OFP_VERSION;
 
  877    opi->header.type = OFPT_PACKET_IN;
 
  878    opi->header.length = htons(buffer->size);
 
  879    opi->header.xid = htonl(0);
 
  880    opi->buffer_id = htonl(packet_uid);
 
  881    opi->total_len = htons(total_len);
 
  882    opi->in_port = htons(in_port);
 
  883    opi->reason = reason;
 
 
  893    std::ostringstream nm;
 
  895    strncpy((
char*)desc->name, nm.str().c_str(), 
sizeof desc->name);
 
  897    p.
netdev->GetAddress().CopyTo(desc->hw_addr);
 
  898    desc->config = htonl(p.
config);
 
  899    desc->state = htonl(p.
state);
 
  904    desc->advertised = 0; 
 
 
  912    ofp_switch_features* ofr =
 
  913        (ofp_switch_features*)
MakeOpenflowReply(
sizeof *ofr, OFPT_FEATURES_REPLY, &buffer);
 
  914    ofr->datapath_id = htonll(
m_id);
 
  915    ofr->n_tables = 
m_chain->n_tables;
 
  920    for (
size_t i = 0; i < 
m_ports.size(); i++)
 
  922        ofp_phy_port* opp = (ofp_phy_port*)ofpbuf_put_zeros(buffer, 
sizeof *opp);
 
 
  933    ofp_vport_table_features* ovtfr =
 
  935                                                     OFPT_VPORT_TABLE_FEATURES_REPLY,
 
  939    ovtfr->max_chain_depth = htons(-1); 
 
  940    ovtfr->mixed_chaining = 
true;
 
 
  951    p.
config &= ~OFPPC_PORT_DOWN;
 
  955        p.
state &= ~OFPPS_LINK_DOWN;
 
  959        p.
state |= OFPPS_LINK_DOWN;
 
  962    return ((orig_config != p.
config) || (orig_state != p.
state));
 
 
  969    ofp_port_status* ops =
 
  971    ops->reason = status;
 
  972    memset(ops->pad, 0, 
sizeof ops->pad);
 
  976    ofpbuf_delete(buffer);
 
 
  983    ofp_flow_expired* ofe =
 
  985    flow_fill_match(&ofe->match, &flow->key);
 
  987    ofe->priority = htons(flow->priority);
 
  988    ofe->reason = reason;
 
  989    memset(ofe->pad, 0, 
sizeof ofe->pad);
 
  991    ofe->duration = htonl(time_now() - flow->created);
 
  992    memset(ofe->pad2, 0, 
sizeof ofe->pad2);
 
  993    ofe->packet_count = htonll(flow->packet_count);
 
  994    ofe->byte_count = htonll(flow->byte_count);
 
 
 1002    ofp_error_msg* oem = (ofp_error_msg*)
MakeOpenflowReply(
sizeof(*oem) + len, OFPT_ERROR, &buffer);
 
 1003    oem->type = htons(type);
 
 1004    oem->code = htons(code);
 
 1005    memcpy(oem->data, 
data, len);
 
 
 1014                                         bool send_to_controller)
 
 1016    sw_flow* flow = chain_lookup(
m_chain, &key);
 
 1020        flow_used(flow, buffer);
 
 1025                            flow->sf_acts->actions,
 
 1026                            flow->sf_acts->actions_len,
 
 1033        if (send_to_controller)
 
 1042    ofpbuf_delete(buffer);
 
 
 1049    ofpbuf* buffer = 
data.buffer;
 
 1055    if (flow_extract(buffer, 
port != -1 ? 
port : OFPP_NONE, &key.flow) &&
 
 1056        (
m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
 
 1058        ofpbuf_delete(buffer);
 
 1066        mpls_h.value = ntohl(*((
uint32_t*)buffer->l2_5));
 
 1067        if (mpls_h.ttl == 1)
 
 1082        if (config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
 
 1083            config & (!eth_addr_equals(key.flow.dl_dst, stp_eth_addr) ? OFPPC_NO_RECV
 
 1084                                                                      : OFPPC_NO_RECV_STP))
 
 1098                        send_to_controller);
 
 
 1104    ofpbuf* buffer = 
m_packetData.find(packet_uid)->second.buffer;
 
 1110    if (flow_extract(buffer, 
port != -1 ? 
port : OFPP_NONE, &key.flow) &&
 
 1111        (
m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
 
 1117    vport_table_entry* vpe = vport_table_lookup(&
m_vportTable, vport);
 
 1129                                 vpe->port_acts->actions,
 
 1130                                 vpe->port_acts->actions_len);
 
 1131        vport_used(vpe, buffer); 
 
 1132        if (!vpe->parent_port_ptr)
 
 1136            if (vpe->parent_port <=
 
 1151        vpe = vpe->parent_port_ptr;
 
 
 1160    ofp_port_mod* opm = (ofp_port_mod*)msg;
 
 1162    int port = opm->port_no; 
 
 1163    if (
port < DP_MAX_PORTS)
 
 1170        if (p.
netdev->GetAddress() != hw_addr)
 
 1177            uint32_t config_mask = ntohl(opm->mask);
 
 1178            p.
config &= ~config_mask;
 
 1179            p.
config |= ntohl(opm->config) & config_mask;
 
 1182        if (opm->mask & htonl(OFPPC_PORT_DOWN))
 
 1184            if ((opm->config & htonl(OFPPC_PORT_DOWN)) && (p.
config & OFPPC_PORT_DOWN) == 0)
 
 1186                p.
config |= OFPPC_PORT_DOWN;
 
 1189            else if ((opm->config & htonl(OFPPC_PORT_DOWN)) == 0 && (p.
config & OFPPC_PORT_DOWN))
 
 1191                p.
config &= ~OFPPC_PORT_DOWN;
 
 
 1218    ofp_switch_config* osc =
 
 1219        (ofp_switch_config*)
MakeOpenflowReply(
sizeof *osc, OFPT_GET_CONFIG_REPLY, &buffer);
 
 
 1229    const ofp_switch_config* osc = (ofp_switch_config*)msg;
 
 1231    int n_flags = ntohs(osc->flags) & (OFPC_SEND_FLOW_EXP | OFPC_FRAG_MASK);
 
 1232    if ((n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_NORMAL &&
 
 1233        (n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_DROP)
 
 1235        n_flags = (n_flags & ~OFPC_FRAG_MASK) | OFPC_FRAG_DROP;
 
 
 1246    const ofp_packet_out* opo = (ofp_packet_out*)msg;
 
 1248    size_t actions_len = ntohs(opo->actions_len);
 
 1250    if (actions_len > (ntohs(opo->header.length) - 
sizeof *opo))
 
 1252        NS_LOG_DEBUG(
"message too short for number of actions");
 
 1256    if (ntohl(opo->buffer_id) == (
uint32_t)-1)
 
 1259        int data_len = ntohs(opo->header.length) - 
sizeof *opo - actions_len;
 
 1260        buffer = ofpbuf_new(data_len);
 
 1261        ofpbuf_put(buffer, (uint8_t*)opo->actions + actions_len, data_len);
 
 1273    flow_extract(buffer, ntohs(opo->in_port), &key.flow); 
 
 1276    if (v_code != ACT_VALIDATION_OK)
 
 1278        SendErrorMsg(OFPET_BAD_ACTION, v_code, msg, ntohs(opo->header.length));
 
 1279        ofpbuf_delete(buffer);
 
 
 1291    const ofp_vport_mod* ovpm = (ofp_vport_mod*)msg;
 
 1293    uint16_t command = ntohs(ovpm->command);
 
 1294    if (command == OFPVP_ADD)
 
 1298    else if (command == OFPVP_DELETE)
 
 1300        if (remove_vport_table_entry(&
m_vportTable, ntohl(ovpm->vport)))
 
 1303                         OFPET_VPORT_MOD_FAILED,
 
 1305                         ntohs(ovpm->header.length));
 
 
 1315    size_t actions_len = ntohs(ofm->header.length) - 
sizeof *ofm;
 
 1318    sw_flow* flow = flow_alloc(actions_len);
 
 1321        if (ntohl(ofm->buffer_id) != (
uint32_t)-1)
 
 1328    flow_extract_match(&flow->key, &ofm->match);
 
 1331    if (v_code != ACT_VALIDATION_OK)
 
 1333        SendErrorMsg(OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
 
 1335        if (ntohl(ofm->buffer_id) != (
uint32_t)-1)
 
 1343    flow->priority = flow->key.wildcards ? ntohs(ofm->priority) : -1;
 
 1344    flow->idle_timeout = ntohs(ofm->idle_timeout);
 
 1345    flow->hard_timeout = ntohs(ofm->hard_timeout);
 
 1346    flow->used = flow->created = time_now();
 
 1347    flow->sf_acts->actions_len = actions_len;
 
 1348    flow->byte_count = 0;
 
 1349    flow->packet_count = 0;
 
 1350    memcpy(flow->sf_acts->actions, ofm->actions, actions_len);
 
 1353    int error = chain_insert(
m_chain, flow);
 
 1356        if (error == -ENOBUFS)
 
 1359                         OFPFMFC_ALL_TABLES_FULL,
 
 1361                         ntohs(ofm->header.length));
 
 1364        if (ntohl(ofm->buffer_id) != (
uint32_t)-1)
 
 1372    if (ntohl(ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
 
 1378            flow_used(flow, buffer);
 
 1379            flow_extract(buffer,
 
 1380                         ntohs(ofm->match.in_port),
 
 1389            ofpbuf_delete(buffer);
 
 
 1403    flow_extract_match(&key, &ofm->match);
 
 1405    size_t actions_len = ntohs(ofm->header.length) - 
sizeof *ofm;
 
 1408    if (v_code != ACT_VALIDATION_OK)
 
 1410        SendErrorMsg((ofp_error_type)OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
 
 1411        if (ntohl(ofm->buffer_id) != (
uint32_t)-1)
 
 1418    uint16_t priority = key.wildcards ? ntohs(ofm->priority) : -1;
 
 1419    int strict = (ofm->command == htons(OFPFC_MODIFY_STRICT)) ? 1 : 0;
 
 1420    chain_modify(
m_chain, &key, priority, strict, ofm->actions, actions_len);
 
 1422    if (ntohl(ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
 
 1427            sw_flow_key skb_key;
 
 1428            flow_extract(buffer,
 
 1429                         ntohs(ofm->match.in_port),
 
 1438            ofpbuf_delete(buffer);
 
 
 1452    const ofp_flow_mod* ofm = (ofp_flow_mod*)msg;
 
 1453    uint16_t command = ntohs(ofm->command);
 
 1455    if (command == OFPFC_ADD)
 
 1459    else if ((command == OFPFC_MODIFY) || (command == OFPFC_MODIFY_STRICT))
 
 1463    else if (command == OFPFC_DELETE)
 
 1466        flow_extract_match(&key, &ofm->match);
 
 1467        return chain_delete(
m_chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
 
 1469    else if (command == OFPFC_DELETE_STRICT)
 
 1473        flow_extract_match(&key, &ofm->match);
 
 1474        priority = key.wildcards ? ntohs(ofm->priority) : -1;
 
 1475        return chain_delete(
m_chain, &key, ofm->out_port, priority, 1) ? 0 : -ESRCH;
 
 
 1486    ofp_stats_reply* osr;
 
 1495    osr = (ofp_stats_reply*)
MakeOpenflowReply(
sizeof *osr, OFPT_STATS_REPLY, &buffer);
 
 1496    osr->type = htons(cb->
s->
type);
 
 1509            osr = (ofp_stats_reply*)ofpbuf_at_assert(buffer, 0, 
sizeof *osr);
 
 1510            osr->flags = ntohs(OFPSF_REPLY_MORE);
 
 
 1537    const ofp_stats_request* rq = (ofp_stats_request*)oh;
 
 1538    size_t rq_len = ntohs(rq->header.length);
 
 1539    int type = ntohs(rq->type);
 
 1540    int body_len = rq_len - offsetof(ofp_stats_request, body);
 
 1550    cb.
rq = (ofp_stats_request*)xmemdup(rq, rq_len);
 
 1560            NS_LOG_WARN(
"failed initialization of stats request type " << type << 
": " 
 1574            "Switch needs to be registered to a controller in order to start the stats reply.");
 
 
 1596    ofp_header* oh = (ofp_header*)msg;
 
 1597    if (ntohs(oh->length) > length)
 
 1601    assert(oh->version == OFP_VERSION);
 
 1608    case OFPT_FEATURES_REQUEST:
 
 1611    case OFPT_GET_CONFIG_REQUEST:
 
 1614    case OFPT_SET_CONFIG:
 
 1615        error = length < 
sizeof(ofp_switch_config) ? -EFAULT : 
ReceiveSetConfig(msg);
 
 1617    case OFPT_PACKET_OUT:
 
 1621        error = length < 
sizeof(ofp_flow_mod) ? -EFAULT : 
ReceiveFlow(msg);
 
 1624        error = length < 
sizeof(ofp_port_mod) ? -EFAULT : 
ReceivePortMod(msg);
 
 1626    case OFPT_STATS_REQUEST:
 
 1629    case OFPT_ECHO_REQUEST:
 
 1632    case OFPT_ECHO_REPLY:
 
 1635    case OFPT_VPORT_MOD:
 
 1636        error = length < 
sizeof(ofp_vport_mod) ? -EFAULT : 
ReceiveVPortMod(msg);
 
 1638    case OFPT_VPORT_TABLE_FEATURES_REQUEST:
 
 1643                     (ofp_bad_request_code)OFPBRC_BAD_TYPE,
 
 
 1679    for (
size_t i = 0; i < 
m_ports.size(); i++)
 
 
a polymophic address class
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
static const uint16_t PROT_NUMBER
ARP protocol number (0x0806)
bool IsNull() const
Check for null implementation.
Ipv4 addresses are stored in host order in this class.
uint32_t Get() const
Get the host-order 32-bit IP address.
static constexpr uint16_t PROT_NUMBER
Protocol number.
Describes an IPv6 address.
static Mac48Address GetMulticast(Ipv4Address address)
static bool IsMatchingType(const Address &address)
void CopyFrom(const uint8_t buffer[6])
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
Network layer to device interface.
PacketType
Packet types are used as they are in Linux.
@ PACKET_HOST
Packet addressed to us.
@ PACKET_OTHERHOST
Packet addressed to someone else.
@ PACKET_BROADCAST
Packet addressed to all.
@ PACKET_MULTICAST
Packet addressed to multicast group.
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
virtual void DoDispose()
Destructor implementation.
A net device that switches multiple LAN segments via an OpenFlow-compatible flow table.
int ReceiveStatsRequest(const void *msg)
void OutputControl(uint32_t packet_uid, int in_port, size_t max_len, int reason)
Sends a copy of the Packet to the controller.
Address GetBroadcast() const override
Mac48Address m_address
Address of this device.
ofi::Port GetSwitchPort(uint32_t n) const
bool IsBroadcast() const override
int ReceiveFeaturesRequest(const void *msg)
Ptr< Node > m_node
Node this device is installed on.
uint64_t m_id
Unique identifier for this switch, needed for OpenFlow.
uint32_t GetNSwitchPorts() const
int ReceiveGetConfigRequest(const void *msg)
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
OpenFlowSwitchNetDevice()
uint32_t GetIfIndex() const override
void * MakeOpenflowReply(size_t openflow_len, uint8_t type, ofpbuf **bufferp)
Generates an OpenFlow reply message based on the type.
Ptr< Channel > GetChannel() const override
void SendFlowExpired(sw_flow *flow, ofp_flow_expired_reason reason)
Send a reply to the controller that a specific flow has expired.
Ptr< BridgeChannel > m_channel
Collection of port channels into the Switch Channel.
void SetNode(Ptr< Node > node) override
int ReceiveVPortMod(const void *msg)
int ReceiveSetConfig(const void *msg)
bool IsLinkUp() const override
void SendPortStatus(ofi::Port p, uint8_t status)
Send a reply about a Port's status to the controller.
Ptr< Node > GetNode() const override
uint16_t m_mtu
Maximum Transmission Unit.
void DoOutput(uint32_t packet_uid, int in_port, size_t max_len, int out_port, bool ignore_no_fwd)
Called from the OpenFlow Interface to output the Packet on either a Port or the Controller.
void RunThroughFlowTable(uint32_t packet_uid, int port, bool send_to_controller=true)
Run the packet through the flow table.
int ReceiveEchoReply(const void *msg)
void ReceiveFromDevice(Ptr< NetDevice > netdev, Ptr< const Packet > packet, uint16_t protocol, const Address &src, const Address &dst, PacketType packetType)
Called when a packet is received on one of the switch's ports.
int ModFlow(const ofp_flow_mod *ofm)
Modify a flow.
static const char * GetManufacturerDescription()
vport_table_t m_vportTable
Virtual Port Table.
bool IsBridge() const override
Return true if the net device is acting as a bridge.
void SendFeaturesReply()
Send a reply about this OpenFlow switch's features to the controller.
void SendVPortTableFeatures()
Send a reply about this OpenFlow switch's virtual port table features to the controller.
Ports_t m_ports
Switch's ports.
Time m_lastExecute
Last time the periodic execution occurred.
int ForwardControlInput(const void *msg, size_t length)
The registered controller calls this method when sending a message to the switch.
bool SetMtu(const uint16_t mtu) override
int UpdatePortStatus(ofi::Port &p)
Update the port status field of the switch port.
uint16_t m_flags
Flags; configurable by the controller.
void SetAddress(Address address) override
Set the address of this interface.
uint16_t GetMtu() const override
void FlowTableLookup(sw_flow_key key, ofpbuf *buffer, uint32_t packet_uid, int port, bool send_to_controller)
Called by RunThroughFlowTable on a scheduled delay to account for the flow table lookup overhead.
int ReceivePacketOut(const void *msg)
void AddLinkChangeCallback(Callback< void > callback) override
uint16_t m_missSendLen
Flow Table Miss Send Length; configurable by the controller.
int ReceivePortMod(const void *msg)
bool NeedsArp() const override
bool SupportsSendFrom() const override
PacketData_t m_packetData
Packet data.
void SetReceiveCallback(NetDevice::ReceiveCallback cb) override
vport_table_t GetVPortTable()
void OutputPort(uint32_t packet_uid, int in_port, int out_port, bool ignore_no_fwd)
Seeks to send out a Packet over the provided output port.
void StatsDone(ofi::StatsDumpCallback *cb_)
Stats callback is done.
void SendErrorMsg(uint16_t type, uint16_t code, const void *data, size_t len)
If an error message happened during the controller's request, send it to the controller.
void OutputPacket(uint32_t packet_uid, int out_port)
Sends a copy of the Packet over the provided output port.
int AddSwitchPort(Ptr< NetDevice > switchPort)
Add a 'port' to a switch device.
Address GetAddress() const override
~OpenFlowSwitchNetDevice() override
int SendOpenflowBuffer(ofpbuf *buffer)
Send a message to the controller.
void SetController(Ptr< ofi::Controller > c)
Set up the Switch's controller connection.
NetDevice::PromiscReceiveCallback m_promiscRxCallback
Promiscuous Rx Callback.
void DoDispose() override
Destructor implementation.
int StatsDump(ofi::StatsDumpCallback *cb_)
Stats callback is ready for a dump.
Time m_lookupDelay
Flow Table Lookup Delay [overhead].
int ReceiveEchoRequest(const void *msg)
int AddFlow(const ofp_flow_mod *ofm)
Add a flow.
int RunThroughVPortTable(uint32_t packet_uid, int port, uint32_t vport)
Run the packet through the vport table.
static TypeId GetTypeId()
Register this type.
NetDevice::ReceiveCallback m_rxCallback
Rx Callback.
void SetIfIndex(const uint32_t index) override
void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb) override
static const char * GetSoftwareDescription()
int OutputAll(uint32_t packet_uid, int in_port, bool flood)
Send packets out all the ports except the originating one.
int AddVPort(const ofp_vport_mod *ovpm)
Add a virtual port to a switch device.
static const char * GetHardwareDescription()
uint32_t m_ifIndex
Interface Index.
ofpbuf * BufferFromPacket(Ptr< const Packet > packet, Address src, Address dst, int mtu, uint16_t protocol)
Takes a packet and generates an OpenFlow buffer from it, loading the packet data as well as its heade...
Address GetMulticast(Ipv4Address multicastGroup) const override
Make and return a MAC multicast address using the provided multicast group.
Ptr< ofi::Controller > m_controller
Connection to controller.
static const char * GetSerialNumber()
void FillPortDesc(ofi::Port p, ofp_phy_port *desc)
Fill out a description of the switch port.
bool IsMulticast() const override
int ReceiveVPortTableFeaturesRequest(const void *msg)
sw_chain * m_chain
Flow Table; forwarding rules.
bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber) override
int ReceiveFlow(const void *msg)
bool IsPointToPoint() const override
Return true if the net device is on a point-to-point link.
int GetSwitchPortIndex(ofi::Port p)
Smart pointer class similar to boost::intrusive_ptr.
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
static constexpr uint8_t PROT_NUMBER
Protocol number (see http://www.iana.org/assignments/protocol-numbers)
Simulation virtual time values and global simulation resolution.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
AttributeValue implementation for Time.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
static constexpr uint8_t PROT_NUMBER
Protocol number (see http://www.iana.org/assignments/protocol-numbers)
Hold an unsigned integer type.
void DoCleanup(void *state)
Cleans any state created by the init or dump functions.
int DoDump(Ptr< OpenFlowSwitchNetDevice > swtch, void *state, ofpbuf *buffer)
Appends statistics for OpenFlowSwitchNetDevice to 'buffer'.
int DoInit(const void *body, int body_len, void **state)
Prepares to dump some kind of statistics on the connected OpenFlowSwitchNetDevice.
ofp_stats_types type
Status type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Ptr< const AttributeChecker > MakeUintegerChecker()
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
void ExecuteVPortActions(Ptr< OpenFlowSwitchNetDevice > swtch, uint64_t packet_uid, ofpbuf *buffer, sw_flow_key *key, const ofp_action_header *actions, size_t actions_len)
Executes a list of virtual port table entry actions.
void ExecuteActions(Ptr< OpenFlowSwitchNetDevice > swtch, uint64_t packet_uid, ofpbuf *buffer, sw_flow_key *key, const ofp_action_header *actions, size_t actions_len, int ignore_no_fwd)
Executes a list of flow table actions.
uint16_t ValidateActions(const sw_flow_key *key, const ofp_action_header *actions, size_t actions_len)
Validates a list of flow table actions.
uint16_t ValidateVPortActions(const ofp_action_header *actions, size_t actions_len)
Validates a list of virtual port table entry actions.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
static uint64_t GenerateId()
Generate an ID.
void discard_buffer(uint32_t id)
#define OFP_SUPPORTED_CAPABILITIES
uint32_t save_buffer(ofpbuf *)
ofpbuf * retrieve_buffer(uint32_t id)
#define OFP_SUPPORTED_VPORT_TABLE_ACTIONS
#define OFP_SUPPORTED_ACTIONS
Ptr< NetDevice > netdev
NetDevice pointer.
unsigned long long int tx_packets
Counter of Tx packets.
unsigned long long int tx_bytes
Counter of Tx bytes.
uint32_t config
Some subset of OFPPC_* flags.
unsigned long long int tx_dropped
Counter of Tx dropped packets.
uint32_t state
Some subset of OFPPS_* flags.
Callback for a stats dump request.
ofp_stats_request * rq
Current stats request.
Stats * s
Handler of the stats request.
void * state
Stats request state data.
Ptr< OpenFlowSwitchNetDevice > swtch
The switch that we're requesting data from.
bool done
Whether we are done requesting stats.