OSDN Git Service

PDL: Add padding fields
authorMyles Watson <mylesgw@google.com>
Fri, 4 Oct 2019 22:59:41 +0000 (15:59 -0700)
committerMyles Watson <mylesgw@google.com>
Mon, 7 Oct 2019 18:13:44 +0000 (11:13 -0700)
Bug: 138260498
Test: bluetooth_packet_parser_test
Change-Id: I6b020b2d47565e8e724e8114a2031be71e8a22ec

gd/packet/parser/Android.bp
gd/packet/parser/fields/all_fields.h
gd/packet/parser/fields/checksum_start_field.cc
gd/packet/parser/fields/padding_field.cc [new file with mode: 0644]
gd/packet/parser/fields/padding_field.h [new file with mode: 0644]
gd/packet/parser/language_l.ll
gd/packet/parser/language_y.yy
gd/packet/parser/packet_def.cc
gd/packet/parser/parent_def.cc
gd/packet/parser/test/generated_packet_test.cc
gd/packet/parser/test/test_packets.pdl

index 1432da6..ebd3d17 100644 (file)
@@ -15,6 +15,7 @@ cc_binary_host {
         "fields/fixed_scalar_field.cc",
         "fields/group_field.cc",
         "fields/packet_field.cc",
+        "fields/padding_field.cc",
         "fields/payload_field.cc",
         "fields/reserved_field.cc",
         "fields/scalar_field.cc",
index 07a3426..8c0aeee 100644 (file)
@@ -27,6 +27,7 @@
 #include "fields/fixed_enum_field.h"
 #include "fields/fixed_scalar_field.h"
 #include "fields/group_field.h"
+#include "fields/padding_field.h"
 #include "fields/payload_field.h"
 #include "fields/reserved_field.h"
 #include "fields/scalar_field.h"
index eb04639..a100aee 100644 (file)
@@ -39,7 +39,6 @@ void ChecksumStartField::GenExtractor(std::ostream&, int, bool) const {}
 void ChecksumStartField::GenGetter(std::ostream&, Size, Size) const {}
 
 bool ChecksumStartField::GenBuilderParameter(std::ostream&) const {
-  // There is no builder parameter for a size field
   return false;
 }
 
diff --git a/gd/packet/parser/fields/padding_field.cc b/gd/packet/parser/fields/padding_field.cc
new file mode 100644 (file)
index 0000000..0ae99c9
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fields/padding_field.h"
+#include "util.h"
+
+const std::string PaddingField::kFieldType = "PaddingField";
+
+PaddingField::PaddingField(int size, ParseLocation loc)
+    : PacketField("padding_" + std::to_string(size * 8), loc), size_(size * 8) {}
+
+const std::string& PaddingField::GetFieldType() const {
+  return PaddingField::kFieldType;
+}
+
+Size PaddingField::GetSize() const {
+  return size_;
+}
+
+Size PaddingField::GetBuilderSize() const {
+  return 0;
+}
+
+std::string PaddingField::GetDataType() const {
+  return "There's no type for Padding fields";
+}
+
+void PaddingField::GenExtractor(std::ostream&, int, bool) const {}
+
+void PaddingField::GenGetter(std::ostream&, Size, Size) const {}
+
+bool PaddingField::GenBuilderParameter(std::ostream&) const {
+  return false;
+}
+
+bool PaddingField::HasParameterValidator() const {
+  return false;
+}
+
+void PaddingField::GenParameterValidator(std::ostream&) const {}
+
+void PaddingField::GenInserter(std::ostream&) const {
+  ERROR(this) << __func__ << ": This should not be called for padding fields";
+}
+
+void PaddingField::GenValidator(std::ostream&) const {}
diff --git a/gd/packet/parser/fields/padding_field.h b/gd/packet/parser/fields/padding_field.h
new file mode 100644 (file)
index 0000000..5c22c1a
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "fields/packet_field.h"
+#include "parse_location.h"
+
+class PaddingField : public PacketField {
+ public:
+  PaddingField(int size, ParseLocation loc);
+
+  static const std::string kFieldType;
+
+  std::string GetField() const;
+
+  virtual const std::string& GetFieldType() const override;
+
+  virtual Size GetSize() const override;
+
+  virtual Size GetBuilderSize() const override;
+
+  virtual std::string GetDataType() const override;
+
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits, bool for_struct) const override;
+
+  virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+
+  virtual bool GenBuilderParameter(std::ostream&) const override;
+
+  virtual bool HasParameterValidator() const override;
+
+  virtual void GenParameterValidator(std::ostream&) const override;
+
+  virtual void GenInserter(std::ostream&) const override;
+
+  virtual void GenValidator(std::ostream&) const override;
+
+ private:
+  Size size_;
+};
index f653bb0..5814ec1 100644 (file)
@@ -57,6 +57,7 @@ string_literal \".*\"
 "_fixed_"               { return(token::FIXED); }
 "_reserved_"            { return(token::RESERVED); }
 "_checksum_start_"      { return(token::CHECKSUM_START); }
+"_padding_"             { return(token::PADDING); }
   /* Types */
 "checksum"              { return(token::CHECKSUM); }
 "custom_field"          { return(token::CUSTOM_FIELD); }
index 0fcc1a1..a36abef 100644 (file)
@@ -69,6 +69,7 @@
 %token CUSTOM_FIELD "custom_field"
 %token CHECKSUM "checksum"
 %token CHECKSUM_START "checksum_start"
+%token PADDING "padding"
 
 %type<enum_definition> enum_definition
 %type<enumeration_values> enumeration_list
@@ -81,6 +82,7 @@
 %type<packet_field_type> type_def_field_definition;
 %type<packet_field_type> scalar_field_definition;
 %type<packet_field_type> checksum_start_field_definition;
+%type<packet_field_type> padding_field_definition;
 %type<packet_field_type> size_field_definition;
 %type<packet_field_type> payload_field_definition;
 %type<packet_field_type> body_field_definition;
@@ -421,6 +423,11 @@ field_definition
       DEBUG() << "Checksum start field\n";
       $$ = $1;
     }
+  | padding_field_definition
+    {
+      DEBUG() << "Padding field\n";
+      $$ = $1;
+    }
   | size_field_definition
     {
       DEBUG() << "Size field\n";
@@ -592,6 +599,13 @@ checksum_start_field_definition
       delete $3;
     }
 
+padding_field_definition
+  : PADDING '[' INTEGER ']'
+    {
+      DEBUG() << "Padding field defined\n";
+      $$ = new PaddingField($3, LOC);
+    }
+
 size_field_definition
   : SIZE '(' IDENTIFIER ')' ':' INTEGER
     {
index 984c747..84a270c 100644 (file)
@@ -105,7 +105,9 @@ void PacketDef::GenValidator(std::ostream& s) const {
   // Get the static offset for all of our fields.
   int bits_size = 0;
   for (const auto& field : fields_) {
-    bits_size += field->GetSize().bits();
+    if (field->GetFieldType() != PaddingField::kFieldType) {
+      bits_size += field->GetSize().bits();
+    }
   }
 
   // Write the function declaration.
index 79216eb..0c32fa2 100644 (file)
@@ -290,8 +290,22 @@ void ParentDef::GenSize(std::ostream& s) const {
     s << ";}\n\n";
   }
 
+  Size padded_size;
+  for (const auto& field : header_fields) {
+    if (field->GetFieldType() == PaddingField::kFieldType) {
+      if (!padded_size.empty()) {
+        ERROR() << "Only one padding field is allowed.  Second field: " << field->GetName();
+      }
+      padded_size = field->GetSize();
+    }
+  }
+
   s << "public:";
   s << "virtual size_t size() const override {";
+  if (!padded_size.empty()) {
+    s << "return " << padded_size.bytes() << ";}";
+    s << "size_t unpadded_size() const {";
+  }
   s << "return (BitsOfHeader() / 8)";
   if (fields_.HasPayload()) {
     s << "+ payload_->size()";
@@ -371,6 +385,11 @@ void ParentDef::GenSerialize(std::ostream& s) const {
       s << "i.RegisterObserver(packet::ByteObserver(";
       s << "[shared_checksum_ptr](uint8_t byte){ shared_checksum_ptr->AddByte(byte);},";
       s << "[shared_checksum_ptr](){ return static_cast<uint64_t>(shared_checksum_ptr->GetChecksum());}));";
+    } else if (field->GetFieldType() == PaddingField::kFieldType) {
+      s << "ASSERT(unpadded_size() <= " << field->GetSize().bytes() << ");";
+      s << "size_t padding_bytes = ";
+      s << field->GetSize().bytes() << " - unpadded_size();";
+      s << "for (size_t padding = 0; padding < padding_bytes; padding++) {i.insert_byte(0);}";
     } else if (field->GetFieldType() == CountField::kFieldType) {
       const auto& vector_name = ((SizeField*)field)->GetSizedFieldName() + "_";
       s << "insert(" << vector_name << ".size(), i, " << field->GetSize().bits() << ");";
index c9665c6..06f60b5 100644 (file)
@@ -1759,6 +1759,72 @@ TEST(GeneratedPacketTest, testOneLengthTypeValueStruct) {
     }
   }
 }
+
+vector<uint8_t> one_length_type_value_struct_padded_20{
+    0x27,  // _size_(payload),
+    // _size_(value):16 type value
+    0x04, 0x00, 0x01, 'o', 'n', 'e',                             // ONE
+    0x04, 0x00, 0x02, 't', 'w', 'o',                             // TWO
+    0x06, 0x00, 0x03, 't', 'h', 'r', 'e', 'e',                   // THREE
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,        // padding to 30
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // padding to 40
+};
+
+vector<uint8_t> one_length_type_value_struct_padded_28{
+    0x27,  // _size_(payload),
+    // _size_(value):16 type value
+    0x04, 0x00, 0x01, 'o', 'n', 'e',                             // ONE
+    0x04, 0x00, 0x02, 't', 'w', 'o',                             // TWO
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                    // padding to 20
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // padding to 30
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // padding to 40
+};
+
+// TODO: Revisit LTV parsing.  Right now, the padding bytes are parsed
+// DEFINE_AND_INSTANTIATE_OneLengthTypeValueStructPaddedReflectionTest(one_length_type_value_struct_padded_20,
+// one_length_type_value_struct_padded_28);
+
+TEST(GeneratedPacketTest, testOneLengthTypeValueStructPaddedGeneration) {
+  std::vector<LengthTypeValueStruct> ltv_vector;
+  LengthTypeValueStruct ltv;
+  ltv.type_ = DataType::ONE;
+  ltv.value_ = {
+      'o',
+      'n',
+      'e',
+  };
+  ltv_vector.push_back(ltv);
+  ltv.type_ = DataType::TWO;
+  ltv.value_ = {
+      't',
+      'w',
+      'o',
+  };
+  ltv_vector.push_back(ltv);
+
+  auto packet = OneLengthTypeValueStructPaddedBuilder::Create(ltv_vector);
+  ASSERT_EQ(one_length_type_value_struct_padded_28.size(), packet->size());
+
+  std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
+  BitInserter it(*packet_bytes);
+  packet->Serialize(it);
+
+  ASSERT_EQ(one_length_type_value_struct_padded_28.size(), packet_bytes->size());
+  for (size_t i = 0; i < one_length_type_value_struct_padded_28.size(); i++) {
+    ASSERT_EQ(one_length_type_value_struct_padded_28[i], packet_bytes->at(i));
+  }
+
+  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
+  auto view = OneLengthTypeValueStructPaddedView::Create(SizedParentView::Create(packet_bytes_view));
+  ASSERT_TRUE(view.IsValid());
+  auto an_array = view.GetOneArray();
+  // TODO: Revisit LTV parsing.  Right now, the padding bytes are parsed
+  // ASSERT_EQ(ltv_vector.size(), an_array.size());
+  for (size_t i = 0; i < ltv_vector.size(); i++) {
+    ASSERT_EQ(ltv_vector[i].type_, an_array[i].type_);
+    ASSERT_EQ(ltv_vector[i].value_, an_array[i].value_);
+  }
+}
 }  // namespace parser
 }  // namespace packet
 }  // namespace bluetooth
index 494acdf..3c24509 100644 (file)
@@ -384,3 +384,13 @@ struct LengthTypeValueStruct {
 packet OneLengthTypeValueStruct {
   one_array : LengthTypeValueStruct[],
 }
+
+packet SizedParent {
+  _size_(payload) : 8,
+  _payload_,
+}
+
+packet OneLengthTypeValueStructPadded : SizedParent {
+  one_array : LengthTypeValueStruct[],
+  _padding_[40],
+}