def post_build(self, pkt, pay): """ need to set the length of the whole PDU manually to avoid any bit fiddling use a dummy class to build the layer content also add padding if frame is < 64 bytes Note: padding only handles Ether/n*Dot1Q/EtherCat (no special mumbo jumbo) :param pkt: raw string containing the current layer :param pay: raw string containing the payload :return: <new current layer> + payload """ class _EtherCatLengthCalc(Packet): """ dummy class used to generate str representation easily """ fields_desc = [ LEBitField('length', None, 11), LEBitField('_reserved', 0, 1), LEBitField('type', 0, 4), ] payload_len = len(pay) # length field is 11 bit if payload_len > 2047: raise ValueError('payload size {} exceeds maximum length {} ' 'of EtherCat message.'.format(payload_len, 2047)) self.length = payload_len vlan_headers_total_size = 0 upper_layer = self.underlayer # add size occupied by VLAN tags while upper_layer and isinstance(upper_layer, Dot1Q): vlan_headers_total_size += 4 upper_layer = upper_layer.underlayer if not isinstance(upper_layer, Ether): raise Exception('missing Ether layer') pad_len = EtherCat.ETHER_FRAME_MIN_LEN - ( EtherCat.ETHER_HEADER_LEN + vlan_headers_total_size + EtherCat.ETHERCAT_HEADER_LEN + payload_len + EtherCat.ETHER_FSC_LEN) if pad_len > 0: pad = Padding() pad.load = b'\x00' * pad_len return raw(_EtherCatLengthCalc(length=self.length, type=self.type)) + pay + raw(pad) else: return raw(_EtherCatLengthCalc(length=self.length, type=self.type)) + pay
def test_eapol_in(self, request, device_id): """Simulate a packet in message posted upstream""" log.info('test_eapol_in', request=request, device_id=device_id) eapol_start = str( Ether(src='00:11:22:33:44:55') / EAPOL(type=1, len=0) / Padding(load=42 * '\x00')) device = self.adapter_agent.get_device(device_id) self.adapter_agent.send_packet_in(logical_device_id=device.parent_id, logical_port_no=1, packet=eapol_start) return '{"status": "sent"}'
def post_build(self, pkt, pay): last_layer = not len(pay) if last_layer and conf.contribs['LLDP'].strict_mode() and \ type(self).__name__ != LLDPDUEndOfLLDPDU.__name__: raise LLDPInvalidLastLayerException('Last layer must be instance ' 'of LLDPDUEndOfLLDPDU - ' 'got {}'. format(type(self).__name__)) under_layer = self.underlayer if under_layer is None: if conf.contribs['LLDP'].strict_mode(): raise LLDPMissingLowerLayer('No lower layer (Ethernet ' 'or Dot1Q) provided.') else: return pkt + pay not_lowest_lldpdu = under_layer.__class__.__base__.__name__ is 'LLDPDU' if not_lowest_lldpdu: return pkt + pay frame_size, under_layer = LLDPDU._dot1q_headers_size(under_layer) if not under_layer or not isinstance(under_layer, Ether): if conf.contribs['LLDP'].strict_mode(): raise LLDPMissingLowerLayer('No Ethernet layer provided.') else: return pkt + pay frame_size += LLDPDU.ETHER_HEADER_LEN frame_size += len(pkt) + len(pay) + LLDPDU.ETHER_FSC_LEN if frame_size < LLDPDU.ETHER_FRAME_MIN_LEN: pad = Padding() pad.load = b'\x00' * (LLDPDU.ETHER_FRAME_MIN_LEN - frame_size) return pkt + pay + raw(pad) else: return pkt + pay