Лучший способ конвертировать код Python в php для вычисления битовой маски для масок SNMP VLAN

У меня есть некоторый код Python, который я хочу использовать в коде PHP на 100%. у вас есть идеи, как я могу конвертировать код??? У меня есть проблемы с преобразованием кода, особенно часть получить бит и установить бит.

Битовая маска считывается с коммутатора через snmp, и маска представляет порты ведьмы в определенном vlan. Пример:

snmpget 1.3.6.1.2.1.17.7.1.4.3.1.2. возвращает строку HEX, например, F100000000000000

Каждая шестнадцатеричная цифра представляет 4 физически порта LAN коммутатора. Первая цифра в этом примере - F, что означает двоичный код 1111. Это означает, что каждый порт из 1-4 находится в vlan.

Если вы хотите только порты 1,2 и 4, маска будет 1101 и находится в шестнадцатеричном формате D.

Цель кода состоит в том, что я хочу знать, например, находится ли порт 15 в vlan или нет (getbitatposition), и если нет, то я могу изменить битовую маску в позиции порта (setbitatposition).

Порт 15, например, находится на 4-м символе слева:

F = порт 1-4

1 = порт 5-8

0 = порт 9-12

0 = порт 13-16 => HEX 0 => двоичный 0000

Чтобы получить порт 15 в vlan, я должен изменить 3-й бит с 0000 на 0010 и преобразовать его обратно в hex => 2.

Новая маска будет например F102000000000000

Код Python:

def convertHexCharacterToInt(char):
    if (char.upper() == "A"):
        return 10
    elif (char.upper() == "B"):
        return 11
    elif (char.upper() == "C"):
        return 12
    elif (char.upper() == "D"):
        return 13
    elif (char.upper() == "E"):
        return 14
    elif (char.upper() == "F"):
        return 15
    else:
        return (int(char))

def convertIntToHexCharacter(integer):
    if (integer < 0 or integer > 15):
        return "-1"

    if (integer < 10):
        return str(integer)
    elif (integer == 10):
        return "A"
    elif (integer == 11):
        return "B"
    elif (integer == 12):
        return "C"
    elif (integer == 13):
        return "D"
    elif (integer == 14):
        return "E"
    elif (integer == 15):
        return "F"   

def __getBitAtPosition(position, bitmap):

    for x in range(0, len(bitmap)):
        mask = 0x8
        for y in range(0, 4):
            if (((x * 4) + y + 1) == position):
                return (convertHexCharacterToInt(bitmap[x]) & mask) != 0
            mask = mask >> 1

    return None

def __setBitAtPosition(position, bitmap, value):

    if (__getBitAtPosition(position, bitmap) == value):
        return bitmap

    charPosition = (position + 3) / 4 - 1
    bitPosition = int(math.fabs((position - (charPosition * 4)) - 4))

    bitValue = 2 ** bitPosition
    fourBitValue = convertHexCharacterToInt(bitmap[charPosition])

    newValue = None

    if (value):
        newValue = fourBitValue + bitValue
    else:
        newValue = fourBitValue - bitValue
    newBitmap = bitmap[:charPosition] + convertIntToHexCharacter(newValue) + bitmap[charPosition + 1:]
    return newBitmap

Это была моя первая попытка, но результат не тот:

private function _convertHexCharacterToInt($char){

    if (strtoupper($char) == "A"){
        return 10;}
    elseif (strtoupper($char) == "B"){
        return 11;}
    elseif (strtoupper($char) == "C"){
        return 12;}
    elseif (strtoupper($char) == "D"){
        return 13;}
    elseif (strtoupper($char) == "E"){
        return 14;}
    elseif(strtoupper($char) == "F"){
        return 15;}
    else {
        return $char;
    }
}

private function _getBitAtPosition($pos,$bitmap){

    foreach(range(0,strlen($bitmap)) as $x){
    $mask=0x8;

    foreach(range(0,3) as $y){
      if((($x * 4) + $y + 1) == $pos){

        if($this->_convertHexCharacterToInt(substr($bitmap,$x,1))&$mask != 0{
          return $this->_convertHexCharacterToInt(substr($bitmap,$x,1))&$mask;
        }

        $mask = $mask >> 1

      }
    }

    }

}

3 ответа

Я могу решить первую часть, я думаю, что это работает:

private function _getBitAtPosition($pos,$bitmap){

    for($x=0;$x<strlen($bitmap);$x++){
    $mask=0x8;

    for($y=0;$y<4;$y++){
      if((($x * 4) + $y + 1) == $pos){
        if((hexdec(substr($bitmap,$x,1))&$mask) != 0){
          return True;
        }       
      }
       $mask = $mask >> 1;
    }

    }

}

Я также нашел, что решение для второй части может быть не хорошим кодом, а функциональным:

private function _setBitAtPosition($pos,$bitmap,$value){

if($this->_getBitAtPosition($pos,$bitmap) == $value){
    return $bitmap;
}

  $charpos = intval((($pos + 3) / 4 - 1));
  $bitpos = abs(($pos - ($charpos * 4)) - 4);
  $bitvalue = pow(2,$bitpos);

$fourbitvalue=hexdec(substr($bitmap,$charpos,1));

$newvalue = 0;

if($value){
    $newvalue = $fourbitvalue + $bitvalue;
} else {
    $newvalue = $fourbitvalue - $bitvalue;
}

$newbitmap = substr($bitmap,0,$charpos).dechex($newvalue).substr($bitmap,$charpos+1);

return $newbitmap;
}

Вот моя функция perl, которая дает список позиций битов, заданных диапазонами. Я использую его для разбора членства в битовой маске, но это не имеет значения. Например:

# ./test.pl 6E
1-2,4-6

# ./test.pl FF
0-7

# ./test.pl 7fe7fffffe
1-10,13-38

Источник:

sub vlans_list {
  my $raw=shift;
  my $cur_vlan=0;
  my $last_vlan=undef;
  my $seq_start=undef;
  my $list=undef;
  foreach my $octet (split('', $raw)) {
    $octet = hex($octet);
    for(my $i=0; $i < 4; $i++) {
      if($octet & 0x8) {
        if(defined($seq_start) && ($cur_vlan-$last_vlan) == 1) {
          $last_vlan=$cur_vlan;
        } elsif(!defined($seq_start)) {
          $seq_start=$cur_vlan;
          $last_vlan=$cur_vlan;
        } else {
          print("ERROR: vlans_list: sequencing error\n");
        };
      } else {
        if(defined($seq_start)) {
          if(defined($list)) {
            $list .= ",$seq_start";
          } else {
            $list = "$seq_start";
          };
          if($seq_start != $last_vlan) {
            $list .= "-$last_vlan";
          };
          $seq_start=undef;
          $last_vlan=undef;
        };
      };
      $cur_vlan++;
      $octet= $octet << 1;
    };
  };
  if(defined($seq_start)) {
    if(defined($list)) {
      $list .= ",$seq_start";
    } else {
      $list = "$seq_start";
    };
    if($seq_start != $last_vlan) {
      $list .= "-$last_vlan";
    };
  };
  if(!defined($list)) {
    $list="";
  };
  return $list;

};
Другие вопросы по тегам