31 Ekim 2018 Çarşamba

HLA Federation Object Model XML (FOM)

Giriş
Federation Object Model (FOM) federasyondaki ortak bilgi modelini temsil eder. Tanımlama niteliklerin alt/üst sınırları, aralıkları, birimleri gibi özellikleri içermez.

Savunma sanayinde kullanılan FOM tiplerinden birisi "RPR Fom 3".

XML
XML olarak şöyledir. objectClass tag'leri iç içe olabilir ve kalıtımı temsil eder.
<objectModel>
  <modelIdentification>...</modelIdentification>
  <objects>
    <objectClass>...</objectClass>
  </objects>
  <interactions>
    <interactionClass>...</interactionClass>
  </interactions>
  <dimensions>
    <dimension>...</dimension>
    ...
  </dimensions>
  <time>
    <timeStamp>...</timeStamp>
    <lookahead>...</lookahead>
  </time>
  <tags>
    <deleteRemoveTag>...</deleteRemoveTag>
  </tags>
  <synchronizations>
    <synchronizationPoint>...</synchronizationPoint>
    ...
  </synchronizations>
  <transportations>
    <transportation>...</transportation>
  </transportations>
  <switches>...</switches>
  <updateRates>
    <updateRate>...</updateRate>
  </updateRates>
  <dataTypes>
    <basicDataRepresentations>...</basicDataRepresentations>
    <simpleDataTypes>...</simpleDataTypes>
    <enumeratedDataTypes>...</enumeratedDataTypes>
    <arrayDataTypes>...</arrayDataTypes>
    <fixedRecordDataTypes>...</fixedRecordDataTypes>
    <variantRecordDataTypes>...</variantRecordDataTypes>
  </dataTypes>
  <notes>
    <note>...</note>
    ...
  </notes>
</objectModel>
DataTypes

Burada kendi veri tiplerimi tanımlarım.

- basicDataRepresentations : HLAinteger gibi tipler tanımlı
simpleDataTyped : IntergerAttribute, ByteAttribute gibi tipler tanımlı
enumeratedDataTypes : Kendi enum tiplerim tanımlı
arrayDataTypes : Kendi array tiplerim tanımlı
fixedRecordDataTypes : Kendi record tiplerim tanımlı
variantRecordDataTypes : Kendi variant record tiplerim tanımlı. Bu sanırım C++'taki union gibi. Bir sürü tipten sadece biri olabiliyor.
<variantRecordData name="..." discriminant="techniqueType" dataType="TechniqueEnum"
  encoding="HLAvariantRecord">

  <alternative enumerator="Frequency" name="Frequency" dataType="FloatAttribute"/>

  <alternative enumerator="Power" name="Power" dataType="FloatAttribute"/>
   ...

</variantRecordData>



30 Ekim 2018 Salı

ARINC 429

Giriş
Veriyolu yerine noktadan noktaya bağlantıların kullanıldığı bir sistem.

Açıklaması şöyle
There is actually quite a lot of difference between ARINC-429 and MIL-STD-1553. They are different because they were developed by two different groups with different needs.

Both started in the 1970's. Before then there was almost no digital data of any kind on a an aircraft. It was almost all analog or discrete. The biggest issue was noise and interference of the signals. The introduction of microprocessors in the early 70's opened up the option for reasonably priced digital bus technology.

The MIL-STD-1553 bus was a major component of the F-16. Like most military programs, this was a push for maximum performance. ARINC-429 came out of the Boeing 757/767 development effort. Civilian aircraft certification doesn't like a lot of risk and the simpler bus architecture made it easier to design, analyze, and certify.

Since then there have been a number of new buses introduced into aviation. Some have lasted longer than others. B777 introduced ARINC-629 and Fibrechannel. B787 uses ARINC 664 for the main buses with a large mix of ARINC-429 and ARINC-825 (CAN bus) as well. There are a number of data concentrators/converters on the aircraft to get data where it needs to go.

The primary reason for moving away from ARINC-429 is that it is a single transmitter/multiple receiver architecture. This results in a large amount of physical wire. That adds weight and requires maintenance. A bus such as ARINC-664, which is based on Ethernet, can significantly reduce wire. The down side is that it costs a lot more and isn't very efficient when all you need is a small, low rate connection to an odd corner of the aircraft. So you end up with a mix of buses.

And B787 opted for fiber optic cable for the ARINC-664 network to reduce interference from high-intensity radio frequency (HIRF) and lightning.

MIL-STD-1553 is a powerful bus, but it's not as good a fit as many of the newer buses available in the commercial market. The military keeps using it because they have a huge installed base of equipment, it's flexible enough to support their newer functional needs, and commonality reduces their logistics costs.

ARINC-429 sticks around because it's cheap and it has its own large installed base as well.
Data Word İçin Resolution
Açıklaması şöyle
The ARINC 429 Word resolution tells you what value the LSB corresponds to. You can also tell what the resolution should be by looking at the Range and Significant Bits.

It doesn't describe the actual electrical signal.


15 Ekim 2018 Pazartesi

IEEE 754

Not :
İngilizcede precision ve accuracy diye iki kelime var. Türkçeye tam nasıl çevrilir bilemedim.
Kelime anlamı olarak precision ile hassasiyet yani ölçülen değerlerin birbirine yakınlığı, Accuracy  ile de doğruluk yani istenilen değere yakınlık, isabet kast ediliyor.

Precision : Bir sayının içerdiği tüm önemli rakamlara (significant digits/figures) denilir. Önemli rakamlarım sayarken mesela en soldaki sıfırlar sayılmaz. Java'da precision soldaki ilk sıfırdan farklı sayıyı sayarak başlıyor. Örneğin 0.012 sayısı için precision 2'dir.

Sayının tam sayı kısmına whole part, küsurat kısmına fractional part veya decimal part deniliyor. Örnek:  
Velocity is a real number that can be expressed as a whole number and a decimal (e.g., 3750.2563...miles per hour).
Sayının kaç tane küsurat hanesi alabileceği ise scale ile belirleniyor.

Not 
IEEE-754 Floating-Point Conversion sitesinden online calculator bulunuyor.

Giriş
Kayan nokta hesaplaması için kullanılan iki standart var. İlki "IEEE 754", ikincisi ise "IEEE 854".
IEEE 754 aynı zamanda IEC 559 olarak ta bilinir

IEEE 754'ten Önce
IEEE 754'ten önce de küsuratlı işlemler yapılabiliyordu. Açıklaması şöyle
The ENIAC did not have an FPU; it used a ten-digit decimal notation, with no floating-point features.

The IBM 704 had one as standard equipment in 1954. It had various floating-point add, subtract, multiply and divide instructions, but no square-root function.

The IBM 650, around the same time, had an optional floating-point module. As best I can tell, it too supported only addition, subtraction, multiplication, and division.
Bir başka açıklama şöyle. Yani 16 bit, 32 bit için daha önceden de farklı şeyler vardı
Q : Did any PC software floating point use non-IEEE format?
A : Turbo Pascal 2.x and the "ordinary" version of Turbo Pascal 3.x used a six-byte floating-point format which offered higher precision than an IEEE single-precision float, 
...
Several earlier 16-bit floating point formats have existed including that of Hitachi's HD61810 DSP 2 of 1982, Scott's WIF [3] and the 3dfx Voodoo Graphics processor. [4]

Tüm Sayılar Temsil Edilemez
Kayan noktalarda unutulmaması gereken bir nokta tüm sayıları temsil etmenin imkanı yoktur!
Örneğin C#'ta birbirine çok yakın ama farklı iki değişken tanımlayalım
var x = -6.2845230102539063;
var y = -6.2845230102539098;
Bu iki değişkeni tam olarak yazdırmaya kalkarsak çok farklı şekillerde temsik edildiklerini görebiliriz.
Console.WriteLine(DoubleConverter.ToExactString(x));
Console.WriteLine(DoubleConverter.ToExactString(y));
Çıktı alarak şunu alırız.
-6.28452301025390625
-6.284523010253909802713678800500929355621337890625

IEEE754 Desteği
C veya C++ IEEE 754 desteğini şart koşmuyor.
The value representation of floating-point types is implementation-defined.
Eğer IEEE754 standardının kullanılıp kullanılmadığını bulmak istiyorsak std::numeric_limits::is_iec559() metodunu kullanırız.

Java ve C# IEEE754 desteği ile geliyor. Ancak Java IEEE754 desteğini Java 1.2'den sonra gevşetmiş durumda. Ara sonuçların (intermediate results) daha fazla bit kullanmasına izin veriyor. strictfp Anahtar Kelimesi yazısına bakabilirsiniz.

Fraction
IEEE754 yerine neden fraction kullanılmadığının açıklaması şöyle
When adding or subtracting fractions, you need to find the least common multiple of the two denominators. That's an expensive operation, much more expensive than adding or subtracting floating points, which just requires shifts.

Multiplication is also more expensive, because now you need to multiply two numbers instead of just one. Similarly for division.

Also, the numerator and denominator of a fraction will eventually grow large, which means you won't be able to store them in the limited memory of an 8-bit system. Floating point deals with this by rounding.

So: It's more expensive, there's no way to limit the memory used for truly general applications, and scientific applications are geared towards using floating point, anyway.

Double
IEEE754- Double yazısına taşıdım.

Float
IEEE 754 - Float yazısına taşıdım.

Half Precison
IEEE 754 Half isimli 16 bit için bir başka standart var. Half Precision Arithmetic yazısına taşıdım.

Denormal Number
IEEE 754 - Denormal Number yazısına taşıdım.

Sayılarda Seyrelme - Sparse Hale Gelme
Kayan noktalarda sayı 0'a yaklaştıkça temsil edilebilen rakamlar daha yoğunlaşırken (dense), 0'dan uzaklaştıkça temsil edilebilen rakamlar seyreliyor. (sparse). Burada 0'dan uzaklaştıkça seyrelme görülebiliyor.

Dolayısıyla float için veri aralığı 3.4E +/- 38  olarak tanılanmasına yani 3400,000,000,000,000,000,000,000,000,000,000,000,000.00 gibi dev bir sayı olmasına rağmen aslında seyrelme yüzünden bazen kullanışsız olabiliyor.

Bu yüzden sum of series using float sorusunda da açıklandığı gibi seri toplama işlemlerinde önce küçük sayıları toplamak hata olasılığını azaltıyor.

Yine aynı şekilde The Patriot Missile Failure yazısında açıklandığı gibi 1/10 gibi bir sayı tam olarak temsil edilemiyor. Eğer belli bir aralığı dolaşmak istersek aşağıdaki gibi int kullanmak daha makul olabilir.

for (int i=100; i>=0; --i)
{    
    float f = i/100.0f;
    ...
}

Intel 80 bit floating point
IEEE 754 Extended Precision yazısına taşıdım.


Yuvarlama İşlemleri
Konuyu IEEE 754 ve Yuvarlama başlıklı yazıya taşıdım.

Integer'dan Cast Etme İşlemleri
C++
Özellikle bazen problem olabiliyormuş. Örnekte
#include <stdio.h>

int main() {
    int x = 2147483647;
    printf("%f\n", (float)2147483647);
    printf("%f\n", (float)x);
    return 0;
}
çıktı olarak şu değerleri alırız.
2147483648.000000
2147483647.000000
Sebep ise şöyle gösterilmiş. 
  • Casting int to float, when the magnitude of the int value is less than FLT_MAX and the int is not a representable value for float, causes either the next-highest or next-lowest float value to be selected, and which one is selected is implementation-defined. (6.3.1.4/2)

Anladığıma göre float tam sayı için daha az bit kullanıyor. Range olarak int değeri kapsasa bile bit olarak sığdıramıyor ve yuvarlama ihtiyacı beliriyor.

Integer'a Cast Etme İşlemleri
Integer'a cast ederken dikkat edilmesi gereken bir nokta, int sayılar daha küçük bit uzunlukları ile temsil edildiklerinden dolayı her double sayı int'e cast edilemeyebilir. Edilirse aritmetik taşma (overflow) riski bulunur. Örneğin The Explosion of the Ariane 5 yazısında 64 bitlik bir double sayının 16 bitlik int'e cast edilmesi sonucu overflow olduğu ve yazılımdaki bu hatanın kazaya sebep olduğu anlatılıyor.
Java
How can I accurately determine if a double is an integer? sorusunda açıklandığı gibi Java dilinde bir double tüm integer değerleri temsil edebilir. Dolayısıyla aşağıdaki örnek işe yarar
if((int)d == d)
Ancak long değerleri sadece 2^52'ye kadar temsil edebilir. Long veri tipi 64 bit olduğu için 2^52^den büyük değeleri temsil edemez.
C++
Is int(doubleValue) guaranteed to be smaller or equal to doubleValue for positive values sorusunda açıklandığı gibi >=0 pozitif veya değeri 0 floating point sayıları int'e cast etme işlemi problemsiz çalışıyor.
Örnek : 

int i = int (doubleNumber) gibi.

Hash İşlemleri
Hash function for floats sorusunda verilen örnek ilginç.

String'e Çevirirken Gösterimsel Yuvarlama İşlemleri
Bir kayan nokta stringe çevirilirken yuvarlamaya maruz kalabilir. Yuvarlama yöntemini seçebilme yeteneği bazı dillerde mevcut.

Java 
Truncate a float and a double in java sorusunda anlatıldığı gibi DecimalFormat sınıfı kullanılabilir. Ayrıca DecimalFormat başlıklı yazıya göz atabilirsiniz.

Burada dikkat edilmesi gereken nokta :
DecimalFormat provides rounding modes defined in RoundingMode for formatting. By default, it uses RoundingMode.HALF_EVEN. 

bash
Floating point rounding in shell sorusuna verilen cevapta da aynı Java'daki gibi Half_Even yuvarlama yönteminin kullanıldığı görülebilir.
 
C
printf anladığım kadarıyla sadece yukarıya yuvarlama yapıyor.

String'e Çevirme İşlemleri
Konuyu IEEE 754 ve String'e Çevirme başlıklı yazıya taşıdım.

String'den Okuma İşlemleri
Konuyu IEEE 754 ve String'den Okuma başlıklı yazıya taşıdım.

Byte'lardan Okuma İşlemleri
Java
How does Float.intBitsToFloat work? sorusunda Float.intBitsToFloat(int) metodunun nasıl çalıştığı gösterilmiş.
Can every float be expressed exactly as a double? sorusuna verilen cevapta ise intBitsToFloat metodu kullanılarak 32 bit ile temsil edilen tüm float'lat yaratılmış ve hepsinin double ile temsil edilebileceği ispatlanmış.

Burada dikkat edilmesi gereken nokta union tanımında bazı yerlerde long , int gibi veri tipler kullanılıyor.C/C++ ile bazı veri tiplerinin büyüklüğü kullanılan platforma göre değişebilir. Data Type Ranges(C++) sayfasında bazı örnekler var. Aşağıdaki tabloda çok kullanılan büyüklükleri görmek mümkün.

long (long int, unsigned long vs.) : genellikle 4 byte
long long (unsigned long long ) : genellikle 8 byte

Ancak double için aşağıdaki gibi bir union tanımlamak her zaman doğru olmayabilir.

union udouble {
  double d;
  unsigned long u; // her zaman doğru olmayabilir.
}
C++
C++ ile elimizde byte[] varsa How can I convert 4 bytes storing an IEEE 754 floating point number to a float value in C? sorusunda açıklandığı gibi 
float f;
char * p = (char *)&f;
p[0] = byte1; 

p[1] = byte2;
şeklinde çevirilebilir.
Özel Sabitler
Konuyu IEEE 754 Özel Sabitler başlıklı yazıya taşıdım.

Özel Sayılar
Konuyu IEEE 754 Özel Sayılar başlıklı yazıya taşıdım.

Sıfıra Çok Yakın Bir Sayı İle Bölme İşlemleri
C++
Bölen sıfır değil ancak sıfıra çok yakın bir sayı olursa veya bölme işleminin sonucu çok büyük olursa Infinity elde edilebilir.

Java
Burada açıklandığı gibi System.out.println(0/0); java.lang.ArithmeticException: / by zero exception'a sebep olurken System.out.println(6.199/0); olmuyor ve infinity dönüyor. Sebebi ise infinity integer olarak temsil edilemiyor ve integer bölme işlemi exception atmak zorunda, ancak infinity kayan nokta olarak temsil edilebiliyor ve IEEE 754 standardı bu durumda exception atmamayı tercih etmiş.

Exception Yakalama
Konuyu IEEE754 ve Exception başlıklı yazıya taşıdım.

İki Sayıyı Karşılaştırma
C++
IEEE 754 ve İki Sayıyı Karşılaştırma yazısına taşıdım.

Fixed Point
Floating point'e baktıktan sonra Fixed Point ile ilgili de biraz yazmak faydalı olabilir. Fixed point artık pek kullanılmıyor. Amacı, örneğin 32 bitlik bir integer'ın 24 bitini ana sayı 8 bitini ise ondalık alan olarak kullanmak.

Arbitrary Precision Arithmetic
Konuyu Arbitrary Precision Arithmetic başlıklı yazıya taşıdım.


IEEE 754 ve Roundtrip İşlemler

Roundtrip Formatlama Nedir
String' çevirip tekrar floating pointe çevirmeyi garanti etmek için kullanılır

C
Şu tarz kodları kullanmamak lazım. Çünkü 56 çok büyük bir rakam
double a = 0.1;
printf("a is %0.56f\n", a);
C++
float için 7 double için 17 precision kullanırız.
float  myfloat  = 3.14159625F;
double mydouble = v;

std::stringstream s;

// Setting the stream state:
s << std::setprecision(9) << v << " "
  << std::setprecision(17) << vv;

float  myfloat_in;
double mydouble_in;

s >> myfloat_in >> mydouble_in;
assert(myfloat == myfloat_in && mydouble == mydouble_in);
C#
R'nin açıklaması şöyle
"R" or "r" Round-trip Result: A string that can round-trip to an identical number. Supported by: Single, Double, and BigInteger. Precision specifier: Ignored.
Basitçe şöyle kullanırız:
double d1 = 0.84551240822557006;
string s = d1.ToString("R");
double d2 = double.Parse(s);
Eğer round trip yapmazsak hatalarla karşılaşabiliriz.
float maxFloat = float.MaxValue;
string s = maxFloat.ToString();
float result = float.Parse(s); // same with Convert.ToSingle(s);

bool mustEqual = (maxFloat == result);
// It returns FALSE, why?


IPV4 Header

Giriş
Şöyledir
0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version|  IHL  |Type of Service|          Total Length         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Identification        |Flags|      Fragment Offset    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Time to Live |    Protocol   |         Header Checksum       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       Source Address                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Destination Address                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IPV4 zarfı şöyle düşünülebilir. 12 byte kontrol bilgisi + 8 byte adres bilgisi. Yani toplam 20 byte.

TCP/IP kullanılan bant genişliği düşük hatlarda Van Jacobson TCP/IP Header Compression kullanılarak byte sayısı düşürülebiliyor.

Struct
IPv4 Header şeklen şöyle. Linux'ta şu satırı dahil ederiz.
#include <netinet/in.h>
typedef struct header
{
  //IP-Header
  unsigned char ip_v:4, ip_hl:4;
  unsigned char ip_tos;       //1 Byte
  unsigned short int ip_len;  //2 Byte
  unsigned short int ip_id;   //2 Byte
  unsigned short int ip_off;  //2 Byte
  unsigned char ip_ttl;       //1 Byte
  unsigned char ip_p;         //1 Byte
  unsigned short int ip_sum;  //2 Byte
  unsigned int ip_src;        //4 Byte
  unsigned int ip_dst;        //4 Byte

}
Yukarıdaki tanımda eksik olan şey makinenin Most Significant Bit'inin (MSB) ne olduğuna dikkat edilmemesi. IPV4 ilginç bir şekilde MSB 0 olacak şekilde tanımlı. Dolayısıyla version ve header alanlarının yeri mimariye göre değişe. Örneğin Linux'ta gerçek kod şöyle tanımlı. Little Endian mimaride MSB 7. bit. Yani en solda. Big Endian'da ise MSB 0. bit yani en sağda. Dolayısıyla ters sırada tanımlı.
struct ip
{
  #if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ip_hl:4;               /* header length */
    unsigned int ip_v:4;                /* version */
  #endif
  #if __BYTE_ORDER == __BIG_ENDIAN
    unsigned int ip_v:4;                /* version */
    unsigned int ip_hl:4;               /* header length */
  #endif
  ...
};
Direkt bellek alanı ile çalışınca bu tür detaylara dikkat etmek gerekiyor. Eğer sadece kod ile çalışsaydık okuma esnasında bu tür detaylara dikkat etmezdik. Yani şu kod çalışırdı.
int ip_vhl; // version and header togather
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f) //split header length
#define IP_V(ip) (((ip)->ip_vhl) >> 4) //split IP version


1. Version Alanı - ip_v
4 bit büyüklüğünde. Bu alanlar sabit. Version her zaman IPv4 olduğu için 4.

2. Header Length Alanı - ip_hl
4 bit büyüklüğünde. IP Header'ın uzunluğu. Data hariçtir. Birim olarak 4 byte kullanır. 20 byte'lık header için 5 değeri yazılır. Bu alan Total Length alanından farklıdır. Şöyle yaparız.
struct ipheader* ip = ....; 
int ip_header_len = ip->iph_ihl * 4; 
Bu alan en çok Ip'den sonra gelen veriye erişmek için kullanılır. Şöyle yaparız.
int ip_header_len = ip->iph_ihl * 4;

struct icmpheader* icmp = (struct icmpheader *) ((u_char *)ip + ip_header_len);

3. Service Type Alanı  - Eski Kullanım 
8 bit büyüklüğünde.İlk 2 bit MBZ (Must be Zero), sonraki 3 bit precedence, sonraki 3 bit Type of Service (ToS) anlamına gelirdi.

3.1 MBZ
Hep sıfırdır.

3.2 Precedence
Precedence ile IP paketleri 0-7 değerleri arasında öncelik kazanabiliyordu. Precedence (ServiceType & 0xE0) >> 5) yapılarak okunur.

3.3 ToS
Açıklama yaz

3. Differentiated Services Code Point - Yeni Kullanım 
3.1 Explicit Congestion Notification - ECN
Bir router'da tıkanıklık olursa, router IP paketindeki bu alanı işaretler.


4. Total Length Alanı- ip_len
2 byte büyüklüğünde. Header + Data yani toplam paket uzunluğu. Byte cinsindendir.
nthos (ip->ip_len) ile okunur. Yani Big Endian olarak kullanılır.

Bu alan en fazla 65,535 değerini alabilir. Ping of death saldırısı bu değerden daha büyük paketlerin gönderilmesine dayanıyordu.

IP fragmentli bir yapıya sahip olabildiği için en büyük zarf 60 byte, en küçük faydalı yük 8 byte olabilir. Bu durumda gönderilebilecek MTU 68 byte olur. Açıklaması şöyle
Every internet module must be able to forward a datagram of 68 octets without further fragmentation. This is because an internet header may be up to 60 octets, and the minimum fragment is 8 octets.

5. Identification  Alanı
2 byte büyüklüğünde. Her IP paketin farklı bir sayı verilir.
Flags Alanı
3 bit büyüklüğünde.

6. Flags Alanı
3 bit büyüklüğünde. 3 tane flag var. Bunlar şöyle
Bit 0 - Reserved
Hep 0
Bit 1 - Don't Fragment (DF)
Açıklaması şöyle
IPv4 packets have a Don't-Fragment (DF) flag which indicates whether routers on the path are allowed to perform fragmentation when the packet doesn't fit the MTU of the next link. If you leave the DF flag off you can just send packets as large as possible on your local link, and routers along the path will fragment if/when necessary. You therefore as a sender don't need to discover the MTU for the whole path.

Only when you tell routers not to fragment IPv4 and turn the DF bit on do you need to learn about lower MTU's further along the path. Routers that would have fragmented will now send back ICMP messages (type 3: Destination Unreachable, subtype 4: Fragmentation Needed and Don't Fragment was Set) and the sender needs to receive these so they can adjust their packet size.

IPv6 doesn't have a DF flag, fragmentation along the path is always prohibited. It therefore behaves in a similar way as IPv4 with the DF flag on. Routers will send back ICMP messages (Type 2: Packet Too Big, it's not a subtype of Destination Unreachable anymore, it now is so important it has its own type) and the sender has to take those into account when determining the packet size.

So whether you have to implement Path MTU Discovery has nothing to do with where in the header the fragmentation is implemented (main header vs extension header), it depends on whether fragmentation is handled along the path or whether the sender has to determine the right packet size. If the routers along the path handle it (IPv4 with DF off) then the sender doesn't need to care, but otherwise (IPv4 with DF on, and IPv6) the sender must be able to receive those ICMP messages so it can adjust its behaviour accordingly.

Bit 2 - More Fragment (MF)
Açıklaması şöyle
Reassembly
A receiver knows that a packet is a fragment if at least one of the following conditions is true:
  • The "more fragments" flag is set. (This is true for all fragments except the last.)
  • The "fragment offset" field is nonzero. (This is true for all fragments except the first.)
The receiver identifies matching fragments using the foreign and local internet address, the protocol ID, and the identification field. The receiver will reassemble the data from fragments with the same ID using both the fragment offset and the more fragments flag. When the receiver receives the last fragment (which has the "more fragments" flag set to 0), it can calculate the length of the original data payload, by multiplying the last fragment's offset by eight, and adding the last fragment's data size. In the example above, this calculation was 495*8 + 540 = 4500 bytes.
When the receiver has all the fragments, it can put them in the correct order, by using their offsets. It can then pass their data up the stack for further processing.
7. Fragment Offset Alanı 
Prefragment yani paketlerin kaynakta bölünmesi ve daha sonra hedef'te birleştirilmesi IP protokolünü ilk tasarlayanların niyetiydi. Açıklama şöyle
I've read that fragmented IP packets "always" become reassembled at their ultimate destination, e.g. the recipient host.
Ancak bu niyet gerçekleşmedi. Açıklaması şöyle
That was the original intent of the Designers of IP, it's not so true nowadays though. Many firewalls will defragment packets because it's difficult to do effective firewalling on fragments.
Bu alanın açıklaması şöyle
To fragment a long internet datagram, an internet protocol module (for example, in a gateway), creates two new internet datagrams and copies the contents of the internet header fields from the long datagram into both new internet headers. The data of the long datagram is divided into two portions on a 8 octet (64 bit) boundary (the second portion might not be an integral multiple of 8 octets, but the first must be). Call the number of 8 octet blocks in the first portion NFB (for Number of Fragment Blocks). The first portion of the data is placed in the first new internet datagram, and the total length field is set to the length of the first datagram. The more-fragments flag is set to one. The second portion of the data is placed in the second new internet datagram, and the total length field is set to the length of the second datagram. The more-fragments flag carries the same value as the long datagram. The fragment offset field of the second new internet datagram is set to the value of that field in the long datagram plus NFB.
IPV6'da Fragment özelliği yok. Açıklaması şöyle
In contrast, IPv6, the next generation of the Internet Protocol, does not allow routers to perform fragmentation; hosts must determine the path MTU before sending datagrams.
IP, Ethernet MTU'dan daha büyük veri göndermek isterse veriyi parçalara böler (fragment). Aynı diziye ait fragmentlerde IP Header'daki identification alanı sabittir. Dizinin son elemanı hariç tüm elemanlarının "More Fragmentation Flag" bayrağına 1 değeri atanır. Ayrıca birleştirme işlemi için "Fragment Offset" alanı atanır.
Açıklaması şöyle.
There are three fields in the IPv4 header that are relavent to fragment detection and reassembly.

-The "fragment offset", a number where a fragment fits into the complete packet.
-The "more fragments" flag, a single bit flag that specifies whether there are more fragments after this one.
- The "ID" field, this identifies which packet a fragment belongs to.

If "fragment offset" and "more fragments" are both zero then it is a complete un-fragmented packet. Otherwise we are dealing with a fragment.
Paketin data kısmının büyüklüğü, son paket hariç 8 byte'ın katı olmalıdır. Eğer router'ın çıkış MTU değeri çok küçük ise paketin kaynağına ICMP mesajı gönderir. Açıklaması şöyle
If the MTU of the outgoing interface is smaller than the packet, the router will fragment the packet unless the DF flag is set. In that case the router will drop the packet and send an ICMP packet too big message back to the sender.

Tam bölünme örneği
Elimizde 302 byte uzunluğunda paket olsun. MTU 128 olsun. Paket şöyle bölünür.
Fragment 1 : 124 byte (20 byte zarf + 104 byte data) 104 / 8 = 13
Fragment 2 : 124 byte (20 byte zarf + 104 byte data) 104 / 8 = 13
Fragment 3 : 94 byte (20 byte zarf + 74 byte data) 104 / 8 = 13
Kısmi bölünme örneği
Elimizde 1396 byte uzunluğunda paket olsun. MTU 1400 byte olsun. Bu örnek için IP zarfının 40 byte olduğunu varsayalım. Ağda ise zarfları çıkarttıktan sonra 1356 byte veri için yer kalır.
1356 / 8 = 169.5
ancak bunu aşağı yuvarlarsak 169 elde ederiz.
169 * 8 = 1352.
Yani bir pakette en fazla 1352 byte gönderebiliriz.Dolayısıyla ilk paket 1352 byte içerir. İkinci paket ise 44 byte içerir. 44 sayısı 8'e tam bölünmez ancak son paket olduğu için 8'in katı olmak zorunda değil.

Kısmi bölünme örneği - 2
Elimizde 4500 byte uzunluğunda paket olsun. MTU ise 2600 olsun. Bu örnek için IP zarfının 40 byte olduğunu varsayalım. Paketler şöyle bölünür. 1924 sayısı 8'e tam bölünmez ancak son paket olduğu için 8'in katı olmak zorunda değil.
Fragment 1: 20 octet IPv4 header and 2576 octet payload . 2576 / 8 = 322
Fragment 2: 20 octet IPv4 header and 1924 octet payload 1924 / 8 = 240.5
8. TTL Alanı - ip_ttl
1 byte büyüklüğünde. 8 bit olduğu için en fazla 255 değerini alabilir. IPV4 için TTL genelde 1 veya 64 veya 128 veya 255 değeri ile dolduruluyor.

Windows ve Linux
Window ve Linux için değerler şöyle.
- Windows 128 ile dolduruyor.
- Linux 64 ile dolduruyor

255 Değeri Yeterli Olur mu ?
Paketin dünyayı dolaşması için 30 civarında hop şu anda yeterli. Dolayısıyla 255 fazla bile gelir.

Aslında TTL değerini ben Hop Count olarak düşünüyordum ancak paketin yaşaması gereken süreyi gösteriyormuş. Açıklaması şöyle.
Time to Live: 8 bits
This field indicates the maximum time the datagram is allowed to remain in the internet system. If this field contains the value zero, then the datagram must be destroyed. This field is modified in internet header processing. The time is measured in units of seconds, but since every module that processes a datagram must decrease the TTL by at least one even if it process the datagram in less than a second, the TTL must be thought of only as an upper bound on the time a datagram may exist. The intention is to cause undeliverable datagrams to be discarded, and to bound the maximum datagram lifetime.
Bir çok router TTL alanını değiştirmiyor. Bu yüzden IPv6'te bu alan "Hop Limit" olarak değiştirilmiş.
TTL 1 olursa açıklaması şöyle. Ingress ingestion yani gelen mesaj anlamına gelir.
TTL is checked on ingress packets and decreased when forwarding (=routing) packets. Accordingly, sending out a packet with TTL=1 will enable it to reach a local destination but it will not be routed.
9. Protocol Number Alanı - ip_p
IP paketinin hangi üst seviye protokole gönderilmesi gerektiğini belirten bir sayı. Açıklaması şöyle
The protocol number is used by the the layer-3 protocol (IPv4 or IPv6) to determine to which layer-4 protocol in the network stack it should send the payload of the packet.
Icmp, Tcp, Udp vs. olabilir. Ethernet paketindeki Type alanı benzer bir mantık kullanarak aynı işlevi görür. Şöyle yaparız.
if (ip->iph_protocol == IPPROTO_ICMP)
{
  ...
}
Tüm liste burada.
- 6 için TCP Header yazısına bakınız.
- 17 için UDP Header yazısına bakınız.
- 50 ve 51 için IPSec yazısına bakınız
- 144 numaralı protocol "any 0-hop protocol" olarak adlandırılır. Çok eskiden kullanılan ve sadece 1
hop gitmesi istenen bir protokoller içindir.

10. Header Checksum Alanı - ip_sum
IPV4, TCP ve UDP hep checksum yöntemini kullanır. IPV6 nedense artık checksum yöntemini kullanmıyor. Bu alan sadece IP Header için checksum'dır. Paketin yükü için checksum değildir.  Açıklaması şöyle
The header checksum in an IP packet only detects errors in the header. There is no trailing checksum in IP. It's up to the upper layers to detect errors in the payload.
TCP ve UDP paketlerinde checksum header + data içindir.

Bazı network kartları checksum hesaplamasını yapabilir. Bu durumda IP protocol stack normalde kendisinin yapması gereken bu görevi devreder. Açıklaması şöyle
IPv4 has 16-bit header checksum. It is calculated using the Internet checksum algorithm. It is much less reliable than Ethernet's FCS, and each router must modify the packet by decrementing hop count (and thus recalculating checksum), so this is not true end-to-end checksum either. Due to the additional workload required on routers, IPv6 has eliminated this checksum.
Paketi tekrar gönderecek router şöyle yapar.
In Ipv4, the receiving router first checks the checksum then decrements TTL and then recomputes the checksum.
11. Source  Ip Address Alanı 
Bu alanın 32 bit yani 4 byte olması tamemen tesadüf. Açıklaması şöyle.
According to Vint Cerf (the father of IP), the IPv4 32-bit address size of was chosen arbitrarily.
UDP iletişiminde bu alan "unicast RPF" kontrolü ile spoofed UDP paketlerini süzmek için kullanılabilir. Böylece DoS saldırıları önlenebilir.

inet_ntop ile 4 byte'lık adresler string'e çevrilir. inet_pton ile string 4'byte'a çevrilebilir.

Adres alanları IPV6'daki gibi 0'ları atarak kısaltarak gösterilmez.

IPV4 Adres Çeşitleri yazısına bakabilirsiniz.

12.  Destination Ip Address Alanı 
Yukarıdaki açıklama ile aynı

13. Options Alanı
Açıklaması şöyle
There are IPv4 options that may increase the packet header size. That is one of the things that IPv6 fixed. The maximum IPv4 packet header length is 60 bytes.
Record Route Option
RFC 791 ile tanımlı ancak kullanılmıyor