@@ -115,6 +115,15 @@ class UBInt64(GenericType):
115
115
_fmt = "!Q"
116
116
117
117
118
+ class UBInt128 (GenericType ):
119
+ """Format character for an Unsigned Long Long.
120
+
121
+ Class for an 128-bit (16-byte) Unsigned Integer.
122
+ """
123
+
124
+ _fmt = "!8H"
125
+
126
+
118
127
class DPID (GenericType ):
119
128
"""DataPath ID. Identifies a switch."""
120
129
@@ -343,6 +352,114 @@ def __deepcopy__(self, memo):
343
352
return IPAddress (address = self ._value , netmask = self .netmask )
344
353
345
354
355
+ class IPv6Address (GenericType ):
356
+ """Defines a IPv6 address."""
357
+
358
+ netmask = UBInt128 ()
359
+
360
+ def __init__ (self , address = "0000:0000:0000:0000:0000:0000:0000:0000/128" ,
361
+ netmask = None ):
362
+ """Create an IPv6Address with the parameters below.
363
+
364
+ Args:
365
+ address (str): IP Address using IPv6.
366
+ Defaults to '0000:0000:0000:0000:0000:0000:0000:0000/128'
367
+ """
368
+ if '/' in address :
369
+ address , netmask = address .split ('/' )
370
+ else :
371
+ netmask = 128 if netmask is None else netmask
372
+
373
+ if address == '::' :
374
+ address = '0:0:0:0:0:0:0:0'
375
+ elif '::' in address :
376
+ temp = address .split (':' )
377
+ index = temp .index ('' )
378
+ temp = [x for x in temp if x != '' ]
379
+ address = temp [:index ] + ['0' ] * (8 - len (temp )) + temp [index :]
380
+ address = ':' .join (address )
381
+
382
+ super ().__init__ (address )
383
+ self .netmask = int (netmask )
384
+
385
+ def pack (self , value = None ):
386
+ """Pack the value as a binary representation.
387
+
388
+ If the value is None the self._value will be used to pack.
389
+
390
+ Args:
391
+ value (str): IP Address with IPv6 format.
392
+
393
+ Returns:
394
+ bytes: The binary representation.
395
+
396
+ Raises:
397
+ struct.error: If the value does not fit the binary format.
398
+
399
+ """
400
+ if isinstance (value , type (self )):
401
+ return value .pack ()
402
+
403
+ if value is None :
404
+ value = self ._value
405
+
406
+ if value .find ('/' ) >= 0 :
407
+ value = value .split ('/' )[0 ]
408
+
409
+ try :
410
+ value = value .split (':' )
411
+ return struct .pack ('!8H' , * [int (x , 16 ) for x in value ])
412
+ except struct .error as err :
413
+ msg = "IPv6Address error. "
414
+ msg += "Class: {}, struct error: {} " .format (type (value ).__name__ ,
415
+ err )
416
+ raise exceptions .PackException (msg )
417
+
418
+ def unpack (self , buff , offset = 0 ):
419
+ """Unpack a binary message into this object's attributes.
420
+
421
+ Unpack the binary value *buff* and update this object attributes based
422
+ on the results.
423
+
424
+ Args:
425
+ buff (bytes): Binary data package to be unpacked.
426
+ offset (int): Where to begin unpacking.
427
+
428
+ Raises:
429
+ Exception: If there is a struct unpacking error.
430
+
431
+ """
432
+ def _int2hex (number ):
433
+ return "{0:0{1}x}" .format (number , 4 )
434
+
435
+ try :
436
+ unpacked_data = struct .unpack ('!8H' , buff [offset :offset + 16 ])
437
+ except struct .error as exception :
438
+ raise exceptions .UnpackException ('%s; %s: %s' % (exception ,
439
+ offset , buff ))
440
+
441
+ transformed_data = ':' .join ([_int2hex (x ) for x in unpacked_data ])
442
+ self ._value = transformed_data
443
+
444
+ def get_size (self , value = None ):
445
+ """Return the IPv6 address size in bytes.
446
+
447
+ Args:
448
+ value: In structs, the user can assign other value instead of
449
+ this class' instance. Here, in such cases, ``self`` is a class
450
+ attribute of the struct.
451
+
452
+ Returns:
453
+ int: The address size in bytes.
454
+
455
+ """
456
+ return 16
457
+
458
+ def __deepcopy__ (self , memo ):
459
+ """Improve deepcopy speed."""
460
+ return IPv6Address (address = self ._value , netmask = self .netmask )
461
+
462
+
346
463
class HWAddress (GenericType ):
347
464
"""Defines a hardware address."""
348
465
0 commit comments