Line data Source code
1 : /* 2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. 3 : * Copyright Contributors to the OpenSDN project 4 : */ 5 : #ifndef vnsw_agent_pkt_vrouter_pkt_io_hpp 6 : #define vnsw_agent_pkt_vrouter_pkt_io_hpp 7 : 8 : #include "control_interface.h" 9 : #include "cmn/agent_stats.h" 10 : #include "vr_types.h" 11 : #include "vr_defs.h" 12 : #include "vr_mpls.h" 13 : 14 : // VrouterControlInterface is implementation of ControlInterface for platforms 15 : // using vrouter. This class assumes agent_hdr defined in 16 : // vrouter/include/vr_defs.h is prepended with control information 17 : class VrouterControlInterface : public ControlInterface { 18 : public: 19 : static const uint32_t kAgentHdrLen = 20 : (sizeof(ether_header) + sizeof(struct agent_hdr)); 21 : 22 2 : VrouterControlInterface() : ControlInterface() { } 23 2 : virtual ~VrouterControlInterface() { 24 2 : vr_cmd_list_.clear(); 25 2 : vr_cmd_params_list_.clear(); 26 2 : agent_cmd_list_.clear(); 27 2 : } 28 : 29 2 : virtual void InitControlInterface() { 30 : // Init and populate vector for translating command types from vrouter 31 : // to agent 32 2 : vr_cmd_list_.insert(vr_cmd_list_.begin(), MAX_AGENT_HDR_COMMANDS, 33 2 : AgentHdr::INVALID); 34 2 : vr_cmd_list_[AGENT_TRAP_ARP] = AgentHdr::TRAP_ARP; 35 2 : vr_cmd_list_[AGENT_TRAP_L2_PROTOCOLS] = AgentHdr::TRAP_L2_PROTOCOL; 36 2 : vr_cmd_list_[AGENT_TRAP_NEXTHOP] = AgentHdr::TRAP_NEXTHOP; 37 2 : vr_cmd_list_[AGENT_TRAP_RESOLVE] = AgentHdr::TRAP_RESOLVE; 38 2 : vr_cmd_list_[AGENT_TRAP_FLOW_MISS] = AgentHdr::TRAP_FLOW_MISS; 39 2 : vr_cmd_list_[AGENT_TRAP_L3_PROTOCOLS] = AgentHdr::TRAP_L3_PROTOCOLS; 40 2 : vr_cmd_list_[AGENT_TRAP_DIAG] = AgentHdr::TRAP_DIAG; 41 2 : vr_cmd_list_[AGENT_TRAP_SOURCE_MISMATCH] = 42 : AgentHdr::TRAP_SOURCE_MISMATCH; 43 2 : vr_cmd_list_[AGENT_TRAP_HANDLE_DF] = AgentHdr::TRAP_HANDLE_DF; 44 2 : vr_cmd_list_[AGENT_TRAP_ZERO_TTL] = AgentHdr::TRAP_ZERO_TTL; 45 2 : vr_cmd_list_[AGENT_TRAP_ICMP_ERROR] = AgentHdr::TRAP_ICMP_ERROR; 46 2 : vr_cmd_list_[AGENT_TRAP_FLOW_ACTION_HOLD] = AgentHdr::TRAP_FLOW_ACTION_HOLD; 47 2 : vr_cmd_list_[AGENT_TRAP_TOR_CONTROL_PKT] = AgentHdr::TRAP_TOR_CONTROL_PKT; 48 2 : vr_cmd_list_[AGENT_TRAP_FLOW_ACTION_HOLD] = AgentHdr::TRAP_FLOW_ACTION_HOLD; 49 2 : vr_cmd_list_[AGENT_TRAP_ROUTER_ALERT] = AgentHdr::TRAP_ROUTER_ALERT; 50 2 : vr_cmd_list_[AGENT_TRAP_MAC_LEARN] = AgentHdr::TRAP_MAC_LEARN; 51 2 : vr_cmd_list_[AGENT_TRAP_MAC_MOVE] = AgentHdr::TRAP_MAC_MOVE; 52 2 : vr_cmd_list_[AGENT_TRAP_MAC_IP_LEARNING] = AgentHdr::TRAP_MAC_IP_LEARNING; 53 2 : vr_cmd_list_[AGENT_TRAP_BFD] = AgentHdr::TRAP_BFD; 54 : // Init and populate vector for translating command params from vrouter 55 : // to agent 56 2 : vr_cmd_params_list_.insert(vr_cmd_params_list_.begin(), MAX_CMD_PARAMS, 57 2 : AgentHdr::MAX_PACKET_CMD_PARAM); 58 2 : vr_cmd_params_list_[CMD_PARAM_PACKET_CTRL] = AgentHdr::PACKET_CMD_PARAM_CTRL; 59 2 : vr_cmd_params_list_[CMD_PARAM_1_DIAG] = AgentHdr::PACKET_CMD_PARAM_DIAG; 60 : 61 : // Init and populate vector for translating command types from agent 62 : // to vrouter 63 2 : agent_cmd_list_.insert(agent_cmd_list_.begin(), AgentHdr::INVALID, 64 2 : MAX_AGENT_HDR_COMMANDS); 65 2 : agent_cmd_list_[AgentHdr::TX_SWITCH] = AGENT_CMD_SWITCH; 66 2 : agent_cmd_list_[AgentHdr::TX_ROUTE] = AGENT_CMD_ROUTE; 67 2 : } 68 : 69 : // Length of header added by implementation of VrouterControlInterface. 70 : // Buffer passed in Send should reserve atleast EncapsulationLength() bytes 71 0 : virtual uint32_t EncapsulationLength() const { 72 0 : return kAgentHdrLen; 73 : } 74 : 75 18137 : int DecodeAgentHdr(AgentHdr *hdr, uint8_t *buff, uint32_t len) { 76 : // Enusure sanity of the packet 77 18137 : if (len <= kAgentHdrLen) { 78 1 : pkt_handler()->agent()->stats()->incr_pkt_invalid_agent_hdr(); 79 1 : pkt_handler()->agent()->stats()->incr_pkt_exceptions(); 80 1 : pkt_handler()->agent()->stats()->incr_pkt_dropped(); 81 1 : return 0; 82 : } 83 : 84 : // Decode agent_hdr 85 18136 : agent_hdr *vr_agent_hdr = 86 : (agent_hdr *) (buff + sizeof(ether_header)); 87 : 88 18136 : hdr->ifindex = ntohs(vr_agent_hdr->hdr_ifindex); 89 18136 : hdr->vrf = ntohs(vr_agent_hdr->hdr_vrf); 90 18136 : hdr->cmd = VrCmdToAgentCmd(ntohs(vr_agent_hdr->hdr_cmd)); 91 18136 : hdr->cmd_param = ntohl(vr_agent_hdr->hdr_cmd_param); 92 18136 : hdr->nh = ntohl(vr_agent_hdr->hdr_cmd_param_1); 93 18136 : hdr->cmd_param_2 = ntohl(vr_agent_hdr->hdr_cmd_param_2); 94 18136 : hdr->cmd_param_3 = ntohl(vr_agent_hdr->hdr_cmd_param_3); 95 18136 : hdr->cmd_param_4 = ntohl(vr_agent_hdr->hdr_cmd_param_4); 96 18136 : hdr->cmd_param_5 = vr_agent_hdr->hdr_cmd_param_5; 97 18136 : if (hdr->cmd == AGENT_TRAP_HANDLE_DF) { 98 0 : hdr->mtu = ntohl(vr_agent_hdr->hdr_cmd_param); 99 0 : hdr->flow_index = ntohl(vr_agent_hdr->hdr_cmd_param_1); 100 : } 101 : 102 18136 : return kAgentHdrLen; 103 : } 104 : 105 : // Handle packet received by VrouterControlInterface 106 : // Format of packet trapped is OUTER_ETH - AGENT_HDR - PAYLOAD 107 18097 : bool Process(const PacketBufferPtr &pkt) { 108 18097 : AgentHdr hdr; 109 18097 : int agent_hdr_len = 0; 110 : 111 18097 : agent_hdr_len = DecodeAgentHdr(&hdr, pkt->data(), pkt->data_len()); 112 18097 : if (agent_hdr_len <= 0) { 113 1 : return false; 114 : } 115 : 116 18096 : pkt->SetOffset(agent_hdr_len); 117 18096 : return ControlInterface::Process(hdr, pkt); 118 18097 : } 119 : 120 2204 : int EncodeAgentHdr(uint8_t *buff, const AgentHdr &hdr) { 121 2204 : memset(buff, 0, sizeof(agent_hdr)); 122 : 123 : // Add outer ethernet header 124 2204 : struct ether_header *eth = (struct ether_header *)buff; 125 2204 : eth->ether_shost[ETHER_ADDR_LEN - 1] = 1; 126 2204 : eth->ether_dhost[ETHER_ADDR_LEN - 1] = 2; 127 2204 : eth->ether_type = htons(ETHERTYPE_IP); 128 : 129 : // Fill agent_hdr 130 2204 : agent_hdr *vr_agent_hdr = (agent_hdr *) (eth + 1); 131 2204 : vr_agent_hdr->hdr_ifindex = htons(hdr.ifindex); 132 2204 : vr_agent_hdr->hdr_vrf = htons(hdr.vrf); 133 2204 : vr_agent_hdr->hdr_cmd = htons(hdr.cmd); 134 2204 : vr_agent_hdr->hdr_cmd_param = htonl(hdr.cmd_param); 135 2204 : vr_agent_hdr->hdr_cmd_param_1 = htonl(hdr.cmd_param_1); 136 2204 : return 0; 137 : } 138 : 139 : // Transmit packet on VrouterControlInterface. 140 : // Format of packet after encapsulation is OUTER_ETH - AGENT_HDR - PAYLOAD 141 2204 : virtual int Send(const AgentHdr &hdr, const PacketBufferPtr &pkt) { 142 2204 : uint16_t agent_hdr_len = kAgentHdrLen; 143 2204 : uint8_t *agent_hdr_buff = new uint8_t [agent_hdr_len]; 144 2204 : EncodeAgentHdr(agent_hdr_buff, hdr); 145 : 146 2204 : int ret = Send(agent_hdr_buff, agent_hdr_len, pkt); 147 2204 : if (ret <= 0) 148 0 : return ret; 149 : 150 2204 : return ret - sizeof(agent_hdr); 151 : } 152 : 153 : virtual int Send(uint8_t *buff, uint16_t buf_len, 154 : const PacketBufferPtr &pkt) = 0; 155 : private: 156 18136 : AgentHdr::PktCommand VrCmdToAgentCmd(uint16_t vr_cmd) { 157 18136 : AgentHdr::PktCommand cmd = AgentHdr::INVALID; 158 18136 : if (vr_cmd < vr_cmd_list_.size()) { 159 18130 : cmd = vr_cmd_list_[vr_cmd]; 160 : } 161 : 162 18136 : return cmd; 163 : } 164 : 165 : AgentHdr::PktCommandParams VrCmdParamtoAgentCmdParam(uint16_t param) { 166 : AgentHdr::PktCommandParams cmd = AgentHdr::MAX_PACKET_CMD_PARAM; 167 : if (param < vr_cmd_params_list_.size()) { 168 : cmd = vr_cmd_params_list_[param]; 169 : } 170 : 171 : return cmd; 172 : } 173 : 174 : uint16_t AgentCmdToVrCmd(AgentHdr::PktCommand agent_cmd) { 175 : assert((uint32_t)agent_cmd < agent_cmd_list_.size()); 176 : return agent_cmd_list_[agent_cmd]; 177 : } 178 : 179 : std::vector<AgentHdr::PktCommand> vr_cmd_list_; 180 : std::vector<AgentHdr::PktCommandParams> vr_cmd_params_list_; 181 : std::vector<uint16_t> agent_cmd_list_; 182 : 183 : DISALLOW_COPY_AND_ASSIGN(VrouterControlInterface); 184 : }; 185 : #endif // vnsw_agent_pkt_vrouter_pkt_io_hpp