--------------------------------------------------------------------------
--- Copyright (c) 2007-2012, ETH Zurich.
+-- Copyright (c) 2007-2013, ETH Zurich.
-- All rights reserved.
--
-- This file is distributed under the terms in the attached LICENSE file.
"audio_nbm",
"e1000",
"e10k",
+ "e10k_vf",
"e10k_q",
"ehci",
"fat16_ebpb",
"omap/omap44xx_sysctrl_padconf_core",
"omap/omap44xx_sysctrl_padconf_wkup",
"omap/omap44xx_usbconf",
+ "pci_sr_iov_cap",
"omap/omap44xx_usbtllhs_config",
"omap/omap44xx_uart3"
], arch <- allArchitectures
/*
- * Copyright (c) 2011, ETH Zurich. All rights reserved.
+ * Copyright (c) 2011, 2013, ETH Zurich. All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
_ 27 rsvd;
};
+ // Undocumented
+ register ciaa rw addr(base, 0x11088) "CIAA" type(uint32);
+ register ciad rw addr(base, 0x1108C) "CIAD" type(uint32);
/************************************
* 8.2.3.5 Interrupt Registers
eimen 1 "EICS Immediate Interrupt Enable";
ll_int 4 "Low latency Credits Increment Rate";
rsc_delay 3 "RSC Delay";
- vt_mode 2 "VT_Mode";
+ vtmode 2 type(vt_mode) "VT_Mode";
_ 14 rsvd;
eiame 1 "Extended Interrupt Auto Mask Enable";
pba_sup 1 "BA Support";
* 8.2.3.12 - 8.2.3.18 TODO
***********************************/
+ // 8.2.3.12.4
+ register sectxminifg rw addr(base, 0x08810) "Security Tx Buffer Minimum IFG" {
+ minsecifg 4 "Minimum IFG between packets";
+ _ 4;
+ sectxdcb 5 "If PFC enabled, set to 0x1f, else set to 0x10";
+ _ 19;
+ };
+
// 8.2.3.12.5
register secrxctrl rw addr(base, 0x08d00) "Security Rx Control" {
secrx_dis 1 "Rx Security Offload Disable Bit";
register rlec rc addr(base, 0x04040) "Receive Length Error Count"
type(uint32);
- // 8.2.23.26
+ // 8.2.3.23.8
+ register ssvpc rc addr(base, 0x08780) "Switch Security Violation Packet Count"
+ type(uint32);
+
+ // 8.2.3.23.26
register gprc ro addr(base, 0x04074) "Good packets recieved count"
type(uint32);
+ // 8.2.3.23.27
+ register gorcl rc addr(base, 0x04088) "Good Octets Received Count Low"
+ type(uint32);
+
+ // 8.2.3.23.28
+ register gorch rc addr(base, 0x0408c) "Good Octets Received Count High"
+ type(uint32);
+
// 8.2.3.23.29
register rxnfgpc rc addr(base, 0x041B0) "Good Rx Non-Filtered Packet Counter"
type(uint32);
- // 8.2.23.32
+ // 8.2.3.23.32
register rxdgpc rc addr(base, 0x02F50) "DMA Good Rx Packet Counter"
type(uint32);
- // 8.2.23.44
+ // 8.2.3.23.44
register gptc rc addr(base, 0x04080) "Good packets trasmitted count"
type(uint32);
- // 8.2.23.47
+ // 8.2.3.23.45
+ register gotcl rc addr(base, 0x04090) "Good octets transmitted count low"
+ type(uint32);
+
+ // 8.2.3.23.46
+ register gotch rc addr(base, 0x04094) "Good octets transmitted count high"
+ type(uint32);
+
+ // 8.2.3.23.47
register txdgpc rc addr(base, 0x087A0) "DMA Good Tx Packet Counter"
type(uint32);
- // 8.2.23.50
+ // 8.2.3.23.50
register ruc rc addr(base, 0x040A4) "Receive Undersize Count"
type(uint32);
- // 8.2.23.51
+ // 8.2.3.23.51
register rfc rc addr(base, 0x040A8) "Receive Fragment Count"
type(uint32);
- // 8.2.23.52
+ // 8.2.3.23.52
register roc rc addr(base, 0x040AC) "Receive Oversize Count"
type(uint32);
- // 8.2.23.53
+ // 8.2.3.23.53
register rjc rc addr(base, 0x040B0) "Receive Jabber Count"
type(uint32);
- // 8.2.23.54
+ // 8.2.3.23.54
register mngprc rc addr(base, 0x040B4) "Management Packets Received Count"
type(uint32);
- // 8.2.23.55
+ // 8.2.3.23.55
register mngpdc rc addr(base, 0x040B8) "Management Packets Dropped Count"
type(uint32);
- // 8.2.23.59
+ // 8.2.3.23.57
+ register torl rc addr(base, 0x040c0) "Total octets received low"
+ type(uint32);
+
+ // 8.2.3.23.58
+ register torh rc addr(base, 0x040c4) "Total octets received high"
+ type(uint32);
+
+ // 8.2.3.23.59
register tpr rc addr(base, 0x040D0) "Total Packets Recieved"
type(uint32);
- // 8.2.23.60
+ // 8.2.3.23.60
register tpt rc addr(base, 0x040D4) "Total Packets Transmitted"
type(uint32);
- // 8.2.23.69
+ // 8.2.3.23.69
register mspdc rc addr(base, 0x04010) "MAC Short Packet Discard Count"
type(uint32);
- // 8.2.23.74
+ // 8.2.3.23.71
+ regarray rqsmr rw addr(base, 0x02300) [32; 0x4] "Receive Queue Statistics Mapping" {
+ q_map0 4 "Map to queue 4*n+0";
+ _ 4;
+ q_map1 4 "Map to queue 4*n+1";
+ _ 4;
+ q_map2 4 "Map to queue 4*n+2";
+ _ 4;
+ q_map3 4 "Map to queue 4*n+3";
+ _ 4;
+ };
+
+ // 8.2.3.23.73
+ regarray tqsm rw addr(base, 0x08600) [32; 0x4] "Transmit Queue Statistics Mapping" {
+ q_map0 4 "Map to queue 4*n+0";
+ _ 4;
+ q_map1 4 "Map to queue 4*n+1";
+ _ 4;
+ q_map2 4 "Map to queue 4*n+2";
+ _ 4;
+ q_map3 4 "Map to queue 4*n+3";
+ _ 4;
+ };
+
+ // 8.2.3.23.74
regarray qprc rc addr(base, 0x01030) [16; 0x40] "Queue Packets Received Count"
type(uint32);
- // 8.2.23.75
+ // 8.2.3.23.75
regarray qprdc rc addr(base, 0x01430) [16; 0x40] "Queue Packets Received Drop Count"
type(uint32);
_ 1 rsvd;
};
+ // 8.2.3.27.5
+ regarray pfvflre ro addr(base, 0x00600) [2] "PF VFLR Events Indication" type(uint32);
+
+ // 8.2.3.27.6
+ regarray pfvflrec rw1c addr(base, 0x00700) [2] "PF VFLR Events Clear" type(uint32);
+
+ // 8.2.3.27.7
+ regarray pfvfre rw addr(base, 0x051e0) [2] "PF VF Receive Enable" type(uint32);
+
+ // 8.2.3.27.8
+ regarray pfvfte rw addr(base, 0x08110) [2] "PF VF Transmit Enable" type(uint32);
+
// 8.2.3.27.9
register pfqde rw addr(base, 0x02F04) "PF PF Queue Drop Enable Register" {
qde 1 "Enable drop of packets from Rx Queue queue_idx";
_ 14 rsvd;
};
+ // 8.2.3.27.11
+ regarray pfvfspoof rw addr(base, 0x08200) [8] "PF VF Anti Spoof Control" {
+ macas 8 "MAC Address Anti-spoofing filter";
+ vlanas 8 "VLAN tag anti-spoofing filter";
+ _ 16;
+ };
+
+ // 8.2.3.27.12
+ register pfdtxgswc rw addr(base, 0x08220) "PFDMA Tx General Switch Control" {
+ lbe 1 "Enables VMDQ loopback";
+ _ 31;
+ };
+
+ // 8.2.3.27.14
+ regarray pfvml2flt rw addr(base, 0x0f000) [64] "PF VM L2 Control" {
+ _ 24;
+ aupe 1 "Accept Untagged Packets Enable";
+ rompe 1 "Receive Overflow Multicast Packets";
+ rope 1 "Receive MAC Filters Overflow";
+ bam 1 "Broadcast accept";
+ mpe 1 "Multicast Promiscuous";
+ _ 3;
+ };
+
// 8.2.3.27.15
regarray pfvlvf rw addr(base, 0x0F100) [64] "PF VM VLAN Pool Filter" {
vlan_id 12 "VLAN tag for pool VLAN filter n";
--- /dev/null
+/*
+ * Copyright (c) 2011, 2013, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+/*
+ * e10k_vf.dev
+ *
+ * DESCRIPTION: Intel 82599 10 GbE Controller Virtual Function
+ *
+ * Numbers in comments refer to the Intel 82599 10 GbE Controller Datasheet,
+ * Revison 2.76, September 2012
+ */
+
+device e10k_vf lsbfirst ( addr base ) "Intel 82599 10 GbE Controller Virtual Function" {
+
+ /************************************
+ * 8.3.5.1 General control registers--VF
+ ***********************************/
+
+ // 8.3.5.1.1
+ register vfctrl wo addr(base, 0x00000) "VF control" {
+ _ 26 rsvd;
+ rst 1 "Device reset";
+ _ 5 rsvd;
+ };
+
+ constants lanid "LAN ID" {
+ lan_0 = 0b00 "LAN 0";
+ lan_1 = 0b01 "LAN 1";
+ lan_not_u1 = 0b10 "LAN ID not used";
+ lan_not_u2 = 0b11 "LAN ID not used";
+ };
+
+ // 8.3.5.1.2
+ register vfstatus ro addr(base, 0x00008) "VF status" {
+ _ 2;
+ lan_id 2 type(lanid) "LAN ID";
+ _ 3;
+ link_up 1 "Linkup Status Indication";
+ _ 2;
+ num_vfs 8 "Num VFs";
+ iov_active 1 "IOV Active";
+ pcie_mes 1 "PCIe Master Enable Status";
+ _ 12;
+ };
+
+ // 8.3.5.1.3
+ constants mac_lnkmode "MAC link mode status" {
+ lms_1g = 0b00 "1 GbE";
+ lms_10g_par = 0b01 "10 GbE parallel";
+ lms_10g_ser = 0b10 "10 GbE serial";
+ lms_aneg = 0b11 "auto-negotiation";
+ };
+
+ constants link_speed "MAC link speed status" {
+ ls_100m = 0b01 "100 Mb/s";
+ ls_1g = 0b10 "1 GbE";
+ ls_10g = 0b11 "10 GbE";
+ };
+
+ register vflinks ro addr(base, 0x00010) "VF Link Status Register" {
+ kxsig_det 1 "A signal is present";
+ fecsig_det 1 "FEC reports signal detected";
+ fecblk_lck 1 "FEC reached block lock";
+ krhberr 1 "10GbE serial KR_PCS high error rate";
+ krpcsbl 1 "10 GbE serial PCS block lock";
+ kxr_annprcv 1 "KX/KX4/KR AN Next Page Received";
+ kxr_anprcv 1 "KX/KX4/KR Backplane Auto Negotiation Page Received";
+ lnk_stat 1 "Link Up and there was no link down from last time read";
+ kx4sig_det 4 "Signal Detect of 10 GbE Parallel (KX4, CX4 or XAUI) (1bit per lane)";
+ krsig_det 1 "Signal Detect of 10 GbE serial (KR or SFI)";
+ l10g_syncst 4 "10G Parallel lane sync status (1bit per lane)";
+ l10g_algst 1 "10 GbE align_status";
+ l1g_syncst 1 "1G sync_status";
+ kxr_anrxid 1 "KX/KX4/KR Backplane Auto Negotiation Rx Idle";
+ l1g_anen 1 "PCS_1 GbE auto-negotiation is enabled";
+ l1g_lnken 1 "1 GbE PCS enabled for 1 GbE and SGMII operation";
+ l10g_lnken 1 "XGXS Enabled for 10 GbE operation";
+ fec_en 1 "Status of forwarderrorcorrection in 10 GbE serial link";
+ l10g_seren 1 "Status of 10 GbE serial PCS (KR PCS) for KR or SFI operation";
+ sgmii_en 1 "Status of SGMII operation";
+ mlink_mode 2 type (mac_lnkmode) "MAC link mode status";
+ lnk_speed 2 type (link_speed) "MAC link speed status";
+ lnk_up 1 "Link is up";
+ kxr_ancomp 1 "KX/KX4/KR backplane auto-negotiation has completed successfully";
+ };
+
+ // NYI:
+ // 8.3.5.1.4 VF Free Running Timer (VFFRTIMER)
+ // 8.3.5.1.5 VF Mailbox (VFMailbox)
+ // 8.3.5.1.6 VF Mailbox Memory (VFMBMEM)
+
+ // 8.3.5.1.7
+ register vfrxmemwrap ro addr(base, 0x03190) "VF Rx Packet Buffer Flush Detect" {
+ tc0_wrap 3 "Packet Buffer 0 Wrap Around Counter";
+ tc0_empty 1 "Packet Buffer 0 Empty";
+ tc1_wrap 3 "Packet Buffer 1 Wrap Around Counter";
+ tc1_empty 1 "Packet Buffer 1 Empty";
+ tc2_wrap 3 "Packet Buffer 2 Wrap Around Counter";
+ tc2_empty 1 "Packet Buffer 2 Empty";
+ tc3_wrap 3 "Packet Buffer 3 Wrap Around Counter";
+ tc3_empty 1 "Packet Buffer 3 Empty";
+ tc4_wrap 3 "Packet Buffer 4 Wrap Around Counter";
+ tc4_empty 1 "Packet Buffer 4 Empty";
+ tc5_wrap 3 "Packet Buffer 5 Wrap Around Counter";
+ tc5_empty 1 "Packet Buffer 5 Empty";
+ tc6_wrap 3 "Packet Buffer 6 Wrap Around Counter";
+ tc6_empty 1 "Packet Buffer 6 Empty";
+ tc7_wrap 3 "Packet Buffer 7 Wrap Around Counter";
+ tc7_empty 1 "Packet Buffer 7 Empty";
+ };
+
+ /************************************
+ * 8.3.5.2 Interrupt Registers--VF
+ ***********************************/
+
+ // 8.3.5.2.1
+ register vfeicr rw1c addr(base, 0x00100) "VF Extended Interrupt Cause" {
+ msix 3 "Indicates an interrupt cause mapped to MSI-X vectors 2:0";
+ _ 29 rsvd;
+ };
+
+ // 8.3.5.2.2
+ register vfeics wo addr(base, 0x00104) "VF Extended Interrupt Cause Set" {
+ msix 3 "Sets to corresponding EICR bit of MSI-X vectors 2:0";
+ _ 29 rsvd;
+ };
+
+ // 8.3.5.2.3
+ register vfeims rw addr(base, 0x00108) "VF Extended Interrupt Mask Set/Read" {
+ msix 3 "Set mask bit for the corresponding EICR bit of MSI-X vectors 2:0";
+ _ 29 rsvd;
+ };
+
+ // 8.3.5.2.4
+ register vfeimc wo addr(base, 0x0010c) "VF Extended Interrupt Mask Clear" {
+ msix 3 "Clear mask bit for the corresponding EICR bit of MSI-X vectors 2:0";
+ _ 29 rsvd;
+ };
+
+ // 8.3.5.2.5
+ register vfeiam rw addr(base, 0x00114) "VF Extended Interrupt Auto Mask Enable" {
+ msix 3 "Auto mask bit for the corresponding EICR bit of MSI-X vectors 2:0";
+ _ 29 rsvd;
+ };
+
+ // 8.3.5.2.6
+/*
+ regtype vfeitrn "VF Extended Interrupt Throttle Register Type" {
+ _ 3 rsvd;
+ itr_int 9 "Minimum inter-interrupt interval";
+ _ 3 rsvd;
+ lli_mod 1 "LLI Moderation";
+ lli_credit 5 "LLI Credit";
+ itr_count 7 "ITR Counter";
+ _ 3 rsvd;
+ cnt_wdis 1 "CNT_WDIS";
+ };
+*/
+ // XXX: Not sure if this is correct...
+ regarray vfeitr rw addr(base, 0x00820) [2]
+ "VF Extended Interrupt Mask Set/Read #0-#1"
+ type(uint32);
+
+ // 8.3.5.2.7
+ regarray vfivar rw addr(base, 0x00120) [4] "VF Interrupt Vector Allocation Registers" {
+ i_alloc0 1 "Defines the MSI-X vector (0 or 1) assigned to Rx queue 2*N for IVAR N register (N = 0..3)";
+ _ 6 rsvd;
+ i_allocval0 1 "Interrupt allocation 0 valid";
+ i_alloc1 1 "The interrupt allocation for Tx queue 2n";
+ _ 6 rsvd;
+ i_allocval1 1 "Interrupt allocation 1 valid";
+ i_alloc2 1 "The interrupt allocation for Rx queue 2n+1";
+ _ 6 rsvd;
+ i_allocval2 1 "Interrupt allocation 2 valid";
+ i_alloc3 1 "The interrupt allocation for Tx queue 2n+1";
+ _ 6 rsvd;
+ i_allocval3 1 "Interrupt allocation 3 valid";
+ };
+
+ // 8.3.5.2.8
+ register vfivar_misc rw addr(base, 0x00140) "VF Miscellaneous Interrupt Vector Allocation" {
+ i_alloc0 2 "MSI-X vector assigned to the mailbox interrupt";
+ _ 5 rsvd;
+ i_allocval0 1 "Interrupt allocation 0 valid";
+ _ 24 rsvd;
+ };
+
+ // 8.3.5.2.9
+ // XXX: Not sure if this is correct...
+ regarray vfrscint rw addr(base, 0x00180) [2] "VF RSC Enable Interrupt" type(uint32);
+
+ // 8.3.5.2.10
+ register vfpbacl rw1c addr(base, 0x00148) "VF MSI-X PBA Clear" {
+ penbit 3 "MSI-X Pending Bits Clear. Reading returns PBA vector.";
+ _ 29 rsvd;
+ };
+
+ /************************************
+ * 8.3.5.3 Receive DMA Registers -- VF
+ ***********************************/
+
+ // 8.3.5.3.1
+ regarray vfrdbal rw addr(base, 0x01000) [8; 0x40]
+ "VF Receive Descriptor Base Address Low (#0-#7)"
+ type(uint32);
+
+ // 8.3.5.3.2
+ regarray vfrdbah rw addr(base, 0x01004) [8; 0x40]
+ "VF Receive Descriptor Base Address High (#0-#7)"
+ type(uint32);
+
+ // 8.3.5.3.3
+ regarray vfrdlen rw addr(base, 0x01008) [8; 0x40]
+ "VF Receive Descriptor Length (#0-#7)"
+ type(uint32);
+
+ // 8.3.5.3.4
+ regarray vfrdh rw addr(base, 0x01010) [8; 0x40]
+ "VF Receive Descriptor Head (#0-#7)"
+ type(uint32);
+
+ // 8.3.5.3.5
+ regarray vfrdt rw addr(base, 0x01018) [8; 0x40]
+ "VF Receive Descriptor Tail (#0-#7)"
+ type(uint32);
+
+ // 8.3.5.3.6
+ regtype rxdctl "Receive Descriptor Control" {
+ _ 25 rsvd;
+ enable 1 "Receive Queue Enable";
+ _ 4 rsvd;
+ vme 1 "VLAN Mode Enable";
+ _ 1 rsvd;
+ };
+
+ regarray vfrxdctl rw addr(base, 0x01028) [8; 0x40]
+ "VF Receive Descriptor Control (#0-#7)"
+ type(rxdctl);
+
+ // 8.3.5.3.7
+ constants rx_desctype "RX Descriptor Type" {
+ legacy = 0b000 "Legacy";
+ adv_1buf = 0b001 "Advanced descriptor one buffer";
+ adv_hdrsp = 0b010 "Advanced descriptor header splitting";
+ adv_usehb = 0b101 "Advanced descriptor header splitting always use header buffer";
+ };
+
+ regtype srrctl "Split Receive Control Registers" {
+ bsz_pkt 5 "Receive Buffer Size for Packet Buffer";
+ _ 3 mbz;
+ bsz_hdr 6 "Receive Buffer Size for Header Buffer";
+ _ 8 rsvd;
+ rdmts 3 "Receive Descriptor Minimum Threshold Size";
+ desctype 3 type(rx_desctype) "Define the descriptor type";
+ drop_en 1 "Drop Enabled";
+ _ 3 rsvd;
+ };
+
+ regarray vfsrrctl rw addr(base, 0x01014) [8; 0x40]
+ "VF Split Receive Control Registers (#0-#7)"
+ type(srrctl);
+
+ // 8.3.5.3.8
+ register vfpsrtype rw addr(base, 0x00300) "VF Replication Packet Split Receive Type" {
+ _ 1 mbz;
+ split_nfs 1 "Split received NFS packets after NFS header";
+ _ 2 mbz;
+ split_tcp 1 "Split received TCP packets after TCP header";
+ split_udp 1 "Split received UDP packets after UDP header";
+ _ 2 mbz;
+ split_ip4 1 "Split received IPv4 packets after IPv4 header";
+ split_ip6 1 "Split received IPv6 packets after IPv6 header";
+ _ 2 mbz;
+ split_l2 1 "Split received L2 packets after L2 header";
+ _ 16 mbz;
+ rqpl 3 "Number of bits to use for RSS redirection";
+ };
+
+ // 8.3.5.3.9
+ constants rsc_maxdesc "Maximum descriptors per Large receive" {
+ max_1desc = 0b00 "Maximum of 1 descriptor per large receive";
+ max_4desc = 0b01 "Maximum of 4 descriptors per large receive";
+ max_8desc = 0b10 "Maximum of 8 descriptors per large receive";
+ max_16desc = 0b11 "Maximum of 16 descriptors per large receive";
+ };
+
+ regtype rscctl "RSC Control" {
+ rsc_en 1 "RSC Enable";
+ _ 1 rsvd;
+ maxdesc 2 type(rsc_maxdesc) "Maximum descriptors per Large receive";
+ _ 28 rsvd;
+ };
+
+ regarray vfrscctl rw addr(base, 0x0102c) [8; 0x40]
+ "RSC Control (#0-#7)"
+ type(rscctl);
+
+ /************************************
+ * 8.3.5.4 Transmit Registers -- VF
+ ***********************************/
+
+ // 8.3.5.4.1
+ regarray vftdbal rw addr(base, 0x02000) [4; 0x40]
+ "VF Transmit Descriptor Base Address Low"
+ type(uint32);
+
+ // 8.3.5.4.2
+ regarray vftdbah rw addr(base, 0x02004) [4; 0x40]
+ "VF Transmit Descriptor Base Address High"
+ type(uint32);
+
+ // 8.3.5.4.3
+ regarray vftdlen rw addr(base, 0x02008) [4; 0x40]
+ "VF Transmit Descriptor Length"
+ type(uint32);
+
+ // 8.3.5.4.4
+ // rw is only partially accurate here. This register must only be written
+ // directly after reset.
+ regarray vftdh rw addr(base, 0x02010) [4; 0x40]
+ "VF Transmit Descriptor Head"
+ type(uint32);
+
+ // 8.3.5.4.5
+ regarray vftdt rw addr(base, 0x02018) [4; 0x40]
+ "VF Transmit Descriptor Tail"
+ type(uint32);
+
+ // 8.3.5.4.6
+ regarray vftxdctl rw addr(base, 0x02028) [4; 0x40] "VF Transmit Descriptor Control" {
+ pthresh 7 "Pre-Fetch Threshold";
+ _ 1 rsvd;
+ hthresh 7 "Host Threshold";
+ _ 1 rsvd;
+ wthresh 7 "Write-Back Threshold";
+ _ 2 rsvd;
+ enable 1 "Transmit Queue Enable";
+ swflsh 1 "Transmit Software Flush";
+ _ 5 rsvd;
+ };
+
+ // 8.3.5.4.7
+ regarray vftdwbal rw addr(base, 0x02038) [4; 0x40] "VF Tx Descriptor Completion Write Back Address Low" {
+ headwb_en 1 "Head Write-Back Enable";
+ _ 1 rsvd;
+ headwb_low 30 "Lowest 32 bits of the head write-back memory location";
+ };
+
+ // 8.3.5.4.8
+ regarray vftdwbah rw addr(base, 0x0203c) [4; 0x40] "VF Tx Descriptor Completion Write Back Address High" {
+ headwb_high 32 "Highest 32 bits of the head write-back memory location";
+ };
+
+ /************************************
+ * 8.3.5.5 DCA Registers -- VF
+ ***********************************/
+
+ // 8.3.5.5.1
+ regtype dca_rxctrl "Rx DCA Control Register" {
+ _ 5 rsvd;
+ rxdca_desc 1 "Descriptor DCA EN";
+ rxdca_hdr 1 "Rx Header DCA EN";
+ rxdca_payl 1 "Payload DCA EN";
+ _ 1 rsvd;
+ rxdesc_rdro 1 "Rx Descriptor Read Relax Order Enable";
+ _ 1 rsvd;
+ rxdesc_wbro 1 mbz "Rx Descriptor Write Back Relax Order Enable";
+ _ 1 rsvd;
+ rxdata_wrro 1 "Rx data Write Relax Order Enable";
+ _ 1 rsvd;
+ rxhdr_ro 1 "Rx Split Header Relax Order Enable";
+ _ 8 rsvd;
+ cpuid 8 "Physical ID";
+ };
+
+ regarray vfdca_rxctrl rw addr(base, 0x0100c) [8; 0x40]
+ "VF Rx DCA Control Register (#0-#7)"
+ type(dca_rxctrl);
+
+ // 8.3.5.5.2
+ regarray vfdca_txctrl rw addr(base, 0x0200c) [8; 0x40] "VF Tx DCA Control Registers" {
+ _ 5 rsvd;
+ txdesc_dca 1 "Descriptor DCA Enable";
+ _ 3 rsvd;
+ txdesc_rdro 1 "Tx Descriptor Read Relax Order Enable";
+ _ 1 rsvd;
+ txdesc_wbro 1 "Relax Order Enable of Tx Descriptor well as head pointer write back";
+ _ 1 rsvd;
+ txdata_rdro 1 "Tx Data Read Relax Order Enable";
+ _ 10 rsvd;
+ cpuid 8 "Physical ID";
+ };
+
+ /************************************
+ * 8.3.5.6 Statistics -- VF
+ ***********************************/
+
+ // 8.3.5.6.1
+ register vfgprc ro addr(base, 0x0101c) "VF Good packets received count"
+ type(uint32);
+
+ // 8.3.5.6.2
+ register vfgptc ro addr(base, 0x0201c) "VF Good packets trasmitted count"
+ type(uint32);
+
+ // 8.3.5.6.3
+ register vfgorc_lsb ro addr(base, 0x01020) "VF Good Octets Received Count Low"
+ type(uint32);
+
+ // 8.3.5.6.4
+ register vfgorc_msb ro addr(base, 0x01024) "VF Good Octets Received Count High"
+ type(uint32);
+
+ // 8.3.5.6.5
+ register vfgotc_lsb ro addr(base, 0x02020) "VF Good Octets Transmitted Count Low"
+ type(uint32);
+
+ // 8.3.5.6.6
+ register vfgotc_msb ro addr(base, 0x02024) "VF Good Octets Transmitted Count High"
+ type(uint32);
+
+ // 8.3.5.6.7
+ register vfmprc ro addr(base, 0x01034) "VF Multicast Packets Received Count"
+ type(uint32);
+};
/*
- * Copyright (c) 2008, ETH Zurich. All rights reserved.
+ * Copyright (c) 2008, 2013, ETH Zurich. All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
register cap_ptr ro pci(base, 0x34) "Capabilities ptr" type(uint8);
register int_line rw pci(base, 0x3c) "Interrupt line" type(uint8);
- register int_pin ro pci(base, 0x3d) "Interrupt ping" type(uint8);
+ register int_pin ro pci(base, 0x3d) "Interrupt pin" type(uint8);
register min_gnt ro pci(base, 0x3e) "Min Gnt" type(uint8);
register max_lat ro pci(base, 0x3f) "Max Lat" type(uint8);
register bar0 pci ( base, 0x10 ) "Base address 0" type(uint32);
register bar1 pci ( base, 0x14 ) "Base address 1" type(uint32);
- register pri_bus pci (base, 0x18) "Primary bus number" type(uint8);
- register sec_bus pci (base, 0x19) "Secondary bus number" type(uint8);
- register sub_bus pci (base, 0x1a) "Subordinate bus number" type(uint8);
- register sec_lat pci (base, 0x1b) "Secondary latency timer" type(uint8);
+ register bcfg pci (base, 0x18) "Bus configuration register" {
+ sec_lat 8 "Secondary latency timer";
+ sub_bus 8 "Subordinate bus number";
+ sec_bus 8 "Secondary bus number";
+ pri_bus 8 "Primary bus number";
+ };
//
// I/O base and limit registers
//
// Memory-mapped I/O base and limit registers
//
-
- regtype membl "Memory-mapped base and limit" {
- addr 12 rw "Low bits of address";
- _ 4;
+
+ register membl pci (base, 0x20) "Memory base and limit" {
+ limit 16 "Limit";
+ base 16 "Base";
};
- register mem_base pci (base, 0x20) "Memory base" type(uint16);
- register mem_limit pci (base, 0x22) "Memory limit" type(uint16);
//
// Prefetchable memory base and limit registers
pritm_dis 1 ro "Primary discard timeout";
back2back 1 ro "Fast back-to-back enable";
sec_reset 1 rw "Secondary bus reset";
- mabort 1 ro "Master abort mode";
+ mabort 1 rw "Master abort mode";
_ 1;
vga 1 rw "VGA enable";
isa 1 rw "ISA enable";
--- /dev/null
+/*
+ * Copyright (c) 2013, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+/*
+ * pci_sr_iov_cap.dev
+ *
+ * DESCRIPTION: PCI SR-IOV Extended Capability
+ *
+ * Numbers in comments refer to the Single Root I/O Virtualization and
+ * Sharing Specification, Revision 1.1, January 20, 2010.
+ */
+
+device pci_sr_iov_cap lsbfirst ( addr base ) "PCI SR-IOV Extended Capability" {
+
+ // 3.3.1
+ register hdr ro addr( base, 0x00 ) "Extended Capabilities Header" {
+ id 16 "PCI Express Extended Capability ID";
+ ver 4 "Capability Version";
+ next 12 "Next Capability Offset";
+ };
+
+ // 3.3.2
+ register caps ro addr( base, 0x04 ) "SR-IOV Capabilities" {
+ vf_migration 1 "VF Migration Capable";
+ ari_preserved 1 "ARI Capable Hierarchy Preserved";
+ _ 19;
+ vf_mig_int 11 "VF Migration Interrupt Message Number";
+ };
+
+ // 3.3.3
+ register ctrl rw addr( base, 0x08 ) "SR-IOV Control" {
+ vf_enable 1 "VF Enable";
+ vf_mig_enable 1 "VF Migration Enable";
+ vf_mig_int_enable 1 "VF Migration Interrupt Enable";
+ vf_mse 1 "VF MSE";
+ ari_capable 1 "ARI Capable Hierarchy";
+ _ 11;
+ };
+
+ // 3.3.4
+ register status rw addr( base, 0x0a ) "SR-IOV Status" {
+ vf_migration 1 "VF Migration Status";
+ _ 15 mbz;
+ };
+
+ // 3.3.5
+ register initialvfs ro addr( base, 0x0c ) "InitialVFs" type(uint16);
+ // 3.3.6
+ register totalvfs ro addr( base, 0x0e ) "TotalVFs" type(uint16);
+ // 3.3.7
+ register numvfs rw addr( base, 0x10 ) "NumVFs" type(uint16);
+ // 3.3.8
+ register fdl ro addr( base, 0x12 ) "Function Dependency Link" type(uint8);
+ // 3.3.9
+ register offset ro addr( base, 0x14 ) "First VF Offset" type(uint16);
+ // 3.3.10
+ register stride ro addr( base, 0x16 ) "VF Stride" type(uint16);
+ // 3.3.11
+ register devid ro addr( base, 0x1a ) "VF Device ID" type(uint16);
+
+ // 3.3.12
+ register sup_psize ro addr( base, 0x1c ) "Supported Page Sizes" type(uint32);
+ // 3.3.13
+ register sys_psize rw addr( base, 0x20 ) "System Page Size" type(uint32);
+
+ // 3.3.14
+ regarray vf_bar rw addr( base, 0x24 ) [6] "VF BAR" type(uint32);
+
+ // 3.3.15
+ register vf_mig_state ro addr( base, 0x3c ) "VF Migration State Array Offset" {
+ bir 3 "VF Migration State BIR";
+ offset 29 "VF Migration State Offset";
+ };
+
+};
NoDep SrcTree "src" Config.libcInc,
NoDep SrcTree "src" "/include/c",
NoDep SrcTree "src" ("/include/target" ./. archFamily),
- NoDep SrcTree "src" "/include/ipv4", -- XXX
+ NoDep SrcTree "src" Config.lwipxxxInc, -- XXX
+ NoDep SrcTree "src" Config.lwipInc,
NoDep InstallTree arch "/include",
NoDep InstallTree arch "/include/dev",
NoDep SrcTree "src" ".",
--------------------------------------------------------------------------
--- Copyright (c) 2007-2010, 2012, ETH Zurich.
+-- Copyright (c) 2007-2010, 2012, 2013, ETH Zurich.
-- All rights reserved.
--
-- This file is distributed under the terms in the attached LICENSE file.
libcInc = if libc == "oldc" then "/include/oldc"
else "/lib/newlib/newlib/libc/include"
+-- Sets the include path for lwIP
+lwipInc :: String
+lwipInc = "/lib/lwip/src/include"
+lwipxxxInc :: String
+lwipxxxInc = "/lib/lwip/src/include/ipv4"
+
-- some defines depend on the architecture/compile options
arch_defines :: Options -> [RuleToken]
arch_defines opts
import Data.Maybe
import Data.List
import Control.Monad
+import Control.Parallel.Strategies
import RuleDefs
import HakeTypes
--
makeDirectories :: [(String, HRule)] -> String
makeDirectories r =
- let alldirs = makeDirs1 (Rules [ rl | (f,rl) <- r ])
+ let alldirs = makeDirs1 (Rules [ rl | (f,rl) <- r ]) `using` parListChunk 200 rdeepseq
marker d = d ./. ".marker"
in unlines ([ "# Directories follow" ] ++
[ "hake_dirs: " ++ (marker d) ++ "\n\n" ++
"\tmkdir -p " ++ d ++ "\n" ++
"\ttouch " ++ (marker d) ++ "\n"
| d <- nub alldirs])
-
+
makeDirs1 :: HRule -> [String]
makeDirs1 (Rules hrules) = concat [ makeDirs1 r | r <- hrules]
makeDirs1 (Include tok) =
--
makeMakefile :: [(String, HRule)] -> String
makeMakefile r =
- unlines $ intersperse "" [makeMakefileSection f rl | (f,rl) <- r]
+ unlines $ intersperse "" ([makeMakefileSection f rl | (f,rl) <- r] `using` parList rdeepseq)
makeMakefileSection :: String -> HRule -> String
makeMakefileSection fname rules =
)
--
+-- Build an Arrakis application binary
+--
+
+arrakisapplication :: Args.Args
+arrakisapplication = Args.defaultArgs { Args.buildFunction = arrakisApplicationBuildFn }
+
+arrakisApplicationBuildFn :: [String] -> String -> Args.Args -> HRule
+arrakisApplicationBuildFn af tf args
+ | debugFlag && trace (Args.showArgs (tf ++ " Arrakis Application ") args) False
+ = undefined
+arrakisApplicationBuildFn af tf args =
+ Rules [ arrakisAppBuildArch af tf args arch | arch <- Args.architectures args ]
+
+arrakisAppGetOptionsForArch arch args =
+ (options arch) { extraIncludes =
+ [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
+ optIncludes = (optIncludes $ options arch) \\
+ [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
+ optFlags = ((optFlags $ options arch) ++ [ Str "-DARRAKIS" ]) \\
+ [ Str f | f <- Args.omitCFlags args ],
+ optCxxFlags = (optCxxFlags $ options arch) \\
+ [ Str f | f <- Args.omitCxxFlags args ],
+ optSuffix = "_for_app_" ++ Args.target args,
+ optLibs = [ In InstallTree arch "/lib/libarrakis.a" ] ++
+ ((optLibs $ options arch) \\
+ [ In InstallTree arch "/lib/libbarrelfish.a" ]),
+ extraFlags = Args.addCFlags args ++ Args.addCxxFlags args,
+ extraLdFlags = [ Str f | f <- Args.addLinkFlags args ],
+ extraDependencies =
+ [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
+ }
+
+arrakisAppBuildArch af tf args arch =
+ let -- Fiddle the options
+ opts = arrakisAppGetOptionsForArch arch args
+ csrcs = Args.cFiles args
+ cxxsrcs = Args.cxxFiles args
+ appname = Args.target args
+ -- XXX: Not sure if this is correct. Currently assuming that if the app
+ -- contains C++ files, we have to use the C++ linker.
+ mylink = if cxxsrcs == [] then link else linkCxx
+ in
+ Rules ( flounderRules opts args csrcs
+ ++
+ [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
+ ++
+ [ compileCFiles opts csrcs,
+ compileCxxFiles opts cxxsrcs,
+ assembleSFiles opts (Args.assemblyFiles args),
+ mylink opts (allObjectPaths opts args) (allLibraryPaths args) appname
+ ]
+ )
+
+--
-- Build a static library
--
-- manually add dependencies for now (it would be better if each library
-- defined each own dependencies locally, but that does not seem to be an
-- easy thing to do currently
-libposixcompat_deps = LibDeps [ LibDep "posixcompat", liblwip_deps,
+libposixcompat_deps = LibDeps [ LibDep "posixcompat",
libvfs_deps_all, LibDep "term_server" ]
liblwip_deps = LibDeps $ [ LibDep x | x <- deps ]
where deps = ["lwip" ,"contmng" ,"net_if_raw" ,"timer" ,"hashtable"]
libnetQmng_deps = LibDeps $ [ LibDep x | x <- deps ]
where deps = ["net_queue_manager", "contmng" ,"procon" , "net_if_raw", "bfdmuxvm"]
-libnfs_deps = LibDeps $ [ LibDep "nfs", liblwip_deps ]
+libnfs_deps = LibDeps $ [ LibDep "nfs" ]
libssh_deps = LibDeps [ libposixcompat_deps, libopenbsdcompat_deps,
LibDep "zlib", LibDep "crypto", LibDep "ssh" ]
libopenbsdcompat_deps = LibDeps [ libposixcompat_deps, LibDep "crypto",
libvfs_deps_all = LibDeps $ vfsdeps [VFS_NFS, VFS_RamFS, VFS_BlockdevFS,
VFS_FAT]
+libvfs_deps_nonfs = LibDeps $ vfsdeps [VFS_RamFS, VFS_BlockdevFS, VFS_FAT]
libvfs_deps_nfs = LibDeps $ vfsdeps [VFS_NFS]
libvfs_deps_ramfs = LibDeps $ vfsdeps [VFS_RamFS]
libvfs_deps_blockdevfs = LibDeps $ vfsdeps [VFS_BlockdevFS]
str2dep :: String -> LibDepTree
str2dep str
| str == "vfs" = libvfs_deps_all
+ | str == "vfs_nonfs" = libvfs_deps_nonfs
| str == "posixcompat" = libposixcompat_deps
| str == "lwip" = liblwip_deps
| str == "netQmng" = libnetQmng_deps
, "net_queue_manager"
, "bfdmuxvm"
, "lwip"
+ , "arranet"
+ , "e1000n"
+ , "e10k"
+ , "e10k_vf"
, "contmng"
, "procon"
, "net_if_raw"
#!/bin/bash
##########################################################################
-# Copyright (c) 2009, 2011, ETH Zurich.
+# Copyright (c) 2009, 2011, 2013, ETH Zurich.
# All rights reserved.
#
# This file is distributed under the terms in the attached LICENSE file.
-i$SRCDIR/hake \
-ihake \
-rtsopts=all \
+ -threaded \
-with-rtsopts="-K32m" \
$SRCDIR/hake/Main.hs $LDFLAGS || exit 1
+ # -eventlog \
+
if [ "$RUN_HAKE" == "No" ] ; then
echo "Not running hake as per your request."
exit
fi
echo "Running hake..."
-./hake/hake --output-filename Makefile --source-dir "$SRCDIR" || exit
+#./hake/hake --output-filename Makefile --source-dir "$SRCDIR" +RTS -s -N -K64M -A64M -ls -lf || exit
+./hake/hake --output-filename Makefile --source-dir "$SRCDIR" +RTS -N -K64M -A64M || exit
cat <<EOF
OK - Hake has bootstrapped. You should now have a Makefile in this
module /x86_64/sbin/ahcid auto
## For networking
-## For qemu, enable rtl8029
module /x86_64/sbin/rtl8029 auto
-
-## For real hardware, enable e1000n
module /x86_64/sbin/e1000n auto
## Other services needed for networking
# this should shrink as targets are ported and move into the generic list above
MODULES_x86_64= \
sbin/cpu \
+ sbin/e1000test \
+ sbin/e10ktest \
+ sbin/e10ktest_vf \
+ sbin/e10k_ctrl \
+ sbin/udpecho_arranet_e1000 \
+ sbin/udpecho_arranet_e10k \
+ sbin/udpecho_arranet_e10kvf \
+ sbin/udpecho_arranet_e1000_recvfrom \
+ sbin/udpecho_arranet_e10k_recvfrom \
sbin/mdbtest_range_query \
sbin/mdbtest_addr_zero \
sbin/mdb_bench \
$(BIN_RCCE_LU) \
sbin/rcce_pingpong \
sbin/serial \
+ sbin/arrakismon \
+ sbin/arrakis_hellotest \
+ sbin/socketpipetest \
sbin/shared_mem_clock_bench \
sbin/sif \
sbin/slideshow \
sbin/angler \
sbin/sshd \
sbin/lshw \
+ sbin/spin \
# the following are broken in the newidc system
MODULES_x86_64_broken= \
DISK=hd.img
AHCI=-device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -drive id=disk,file=$(DISK),if=none
+MENU_LST=-kernel $(shell sed -rne 's,^kernel[ \t]*/([^ ]*).*,\1,p' menu.lst) \
+ -append '$(shell sed -rne 's,^kernel[ \t]*[^ ]*[ \t]*(.*),\1,p' menu.lst)' \
+ -initrd '$(shell sed -rne 's,^module(nounzip)?[ \t]*/(.*),\2,p' menu.lst | awk '{ if(NR == 1) printf($$0); else printf("," $$0) } END { printf("\n") }')'
+
ifeq ($(ARCH),x86_64)
- QEMU_CMD=qemu-system-x86_64 -no-kvm -smp 2 -m 1024 -net nic,model=ne2k_pci -net user $(AHCI) -fda $(SRCDIR)/tools/grub-qemu.img -tftp $(PWD) -nographic
+ QEMU_CMD=qemu-system-x86_64 -smp 2 -m 1024 -net nic,model=e1000 -net user $(AHCI) -nographic $(MENU_LST)
GDB=x86_64-pc-linux-gdb
CLEAN_HD=qemu-img create $(DISK) 10M
else ifeq ($(ARCH),x86_32)
"unixsock",
"bcache",
"replay",
+ "arrakis",
+ "e10k_vf",
"empty"],
arch <- allArchitectures
] ++
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+interface arrakis "Interface to arrakismon" {
+ rpc spawn_arrakis_domain(in string path, in char argvbuf[argvbytes],
+ in char envbuf[envbytes], out errval err, out domainid domain_id);
+};
/*
- * Copyright (c) 2012, ETH Zurich.
+ * Copyright (c) 2007-2011, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
*/
-#ifndef BARRELFISH_LWIP_H
-#define BARRELFISH_LWIP_H
-
-#include <errors/errno.h>
-#include <lwip/err.h>
-
-errval_t lwip_err_to_errval(err_t e);
-
-#endif
+interface e10k_vf "e10k VF/PF interface" {
+ rpc get_mac_address(in uint8 vfn, out uint64 mac);
+ rpc init_done(in uint8 vfn);
+};
| f <- [
"cpiobin.h",
"dlfcn.h",
- "lwipopts.h",
"multicast.h",
"utime.h",
"values.h",
*/
/*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
"r" (a8), "r" (a9), "r" (a11), "r" (a12), "r" (syscall_num) \
: "r11", "rcx");
#else /* DEBUG */
-# define BF_SYSCALL_ASM(arg11, label) \
+# ifndef ARRAKIS
+# define BF_SYSCALL_ASM(arg11, label) \
__asm volatile("pushq %%rbp \n\t" \
"movq %%rcx, %%rbp \n\t" \
"syscall \n\t" \
"+r" (a3), "+r" (a4), "+r" (a5), "+r" (syscall_num) \
: "r" (a6), "r" (a7), "r" (a8), "r" (a9), "r" (a12) \
: "r11");
+#else
+# define BF_SYSCALL_ASM(arg11, label) \
+ __asm volatile("pushq %%rbp \n\t" \
+ "movq %%rcx, %%rbp \n\t" \
+ "vmmcall \n\t" \
+ label \
+ "popq %%rbp \n\t" \
+ : "+a" (a10_ret1), "+c" (arg11), "+d" (a2_ret2), "+r" (a1), \
+ "+r" (a3), "+r" (a4), "+r" (a5), "+r" (syscall_num) \
+ : "r" (a6), "r" (a7), "r" (a8), "r" (a9), "r" (a12) \
+ : "r11");
+#endif
#endif
/* NB: We use a10_ret (in the rax register) as both input and output
*/
/*
- * Copyright (c) 2010, ETH Zurich.
+ * Copyright (c) 2010, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
/**
* State of EFLAGS when executing a user-space program: Enable interrupts
*/
-#define USER_CS 0x23
-#define USER_SS 0x1b
+#ifndef ARRAKIS
+// Unprivileged mode
+# define USER_CS 0x23
+# define USER_SS 0x1b
+#else
+// Privileged mode
+# define USER_CS 0x8
+# define USER_SS 0x10
+#endif
+
#define USER_EFLAGS 0x202
#endif // ARCH_X86_64_BARRELFISH_KPI_EFLAGS_H
#include <lwip/sockets.h>
+const char *
+inet_ntop(int af, const void * __restrict src, char * __restrict dst,
+ socklen_t size);
+int inet_pton(int af, const char * __restrict src, void * __restrict dst);
+
#endif
--- /dev/null
+/*
+ * Copyright (c) 2014, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich.
+ * Attn: Systems Group.
+ */
+
+#ifndef ARRAKIS_ARRANET_H
+#define ARRAKIS_ARRANET_H
+
+struct packet {
+ struct packet *next;
+ uint8_t *payload;
+ lpaddr_t pa;
+ size_t len;
+ uint64_t flags;
+ struct socket *sock;
+ void *opaque;
+};
+
+typedef void (*arranet_tx_done_fn)(void *opaque);
+
+int recvfrom_arranet(int sockfd, void **buf, struct packet **p,
+ struct sockaddr *src_addr, socklen_t *addrlen);
+void arranet_recv_free(struct packet *p);
+int sendmsg_arranet(int sockfd, const struct msghdr *msg);
+void arranet_register_tx_done_callback(arranet_tx_done_fn callback);
+
+#define SENDMSG_WITH_COPY
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2014, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich.
+ * Attn: Systems Group.
+ */
+
+#ifndef ARRANET_DEBUG_H
+#define ARRANET_DEBUG_H
+
+//#define DEBUG_LATENCIES
+
+//#include <lwip/udp.h>
+#include <arranet_impl.h>
+#include <barrelfish/sys_debug.h>
+
+#define POSIX_TRANSA 1000
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#define timersub(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) { \
+ --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+ } while (0)
+
+ /**
+ * Definition of the header structure for a request packet.
+ * See section 2
+ */
+ typedef union {
+ struct {
+ uint8_t magic;
+ uint8_t opcode;
+ uint16_t keylen;
+ uint8_t extlen;
+ uint8_t datatype;
+ uint16_t reserved;
+ uint32_t bodylen;
+ uint32_t opaque;
+ uint64_t cas;
+ } request;
+ uint8_t bytes[24];
+ } protocol_binary_request_header;
+
+ /**
+ * Definition of the header structure for a response packet.
+ * See section 2
+ */
+ typedef union {
+ struct {
+ uint8_t magic;
+ uint8_t opcode;
+ uint16_t keylen;
+ uint8_t extlen;
+ uint8_t datatype;
+ uint16_t status;
+ uint32_t bodylen;
+ uint32_t opaque;
+ uint64_t cas;
+ } response;
+ uint8_t bytes[24];
+ } protocol_binary_response_header;
+
+ /**
+ * Definition of a request-packet containing no extras
+ */
+ typedef union {
+ struct {
+ protocol_binary_request_header header;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_request_header)];
+ } protocol_binary_request_no_extras;
+
+ /**
+ * Definition of a response-packet containing no extras
+ */
+ typedef union {
+ struct {
+ protocol_binary_response_header header;
+ } message;
+ uint8_t bytes[sizeof(protocol_binary_response_header)];
+ } protocol_binary_response_no_extras;
+
+typedef struct {
+ uint16_t req_id;
+ uint16_t seq_id;
+ uint16_t n_data;
+ uint16_t extras;
+} memcached_udp_header;
+
+#define UDP_HEADLEN sizeof(memcached_udp_header)
+
+static inline int get_time(void)
+{
+ uint64_t now = rdtsc();
+ static uint64_t tscperms = 0;
+
+ if(tscperms == 0) {
+ errval_t err = sys_debug_get_tsc_per_ms(&tscperms);
+ assert(err_is_ok(err));
+ assert(tscperms >= 100000);
+ }
+
+ uint64_t tod_us = now / (tscperms / 100000);
+
+ return tod_us;
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2014, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich.
+ * Attn: Systems Group.
+ */
+
+#ifndef ARRANET_IMPL_H
+#define ARRANET_IMPL_H
+
+#ifndef ETHARP_HWADDR_LEN
+#define ETHARP_HWADDR_LEN 6
+#endif
+
+PACK_STRUCT_BEGIN
+struct eth_addr {
+ PACK_STRUCT_FIELD(u8_t addr[ETHARP_HWADDR_LEN]);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+PACK_STRUCT_BEGIN
+/** Ethernet header */
+struct eth_hdr {
+#if ETH_PAD_SIZE
+ PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
+#endif
+ PACK_STRUCT_FIELD(struct eth_addr dest);
+ PACK_STRUCT_FIELD(struct eth_addr src);
+ PACK_STRUCT_FIELD(u16_t type);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE)
+
+PACK_STRUCT_BEGIN
+/** the ARP message, see RFC 826 ("Packet format") */
+struct etharp_hdr {
+ PACK_STRUCT_FIELD(u16_t hwtype);
+ PACK_STRUCT_FIELD(u16_t proto);
+ PACK_STRUCT_FIELD(u8_t hwlen);
+ PACK_STRUCT_FIELD(u8_t protolen);
+ PACK_STRUCT_FIELD(u16_t opcode);
+ PACK_STRUCT_FIELD(struct eth_addr shwaddr);
+ PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
+ PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
+ PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define SIZEOF_ETHARP_HDR 28
+#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR)
+
+#define ETHTYPE_ARP 0x0806U
+#define ETHTYPE_IP 0x0800U
+#define ETHTYPE_VLAN 0x8100U
+#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */
+#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */
+
+#define ETH_PAD_SIZE 0
+
+/** ARP message types (opcodes) */
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+
+PACK_STRUCT_BEGIN
+struct ip_hdr {
+ /* version / header length */
+ PACK_STRUCT_FIELD(u8_t _v_hl);
+ /* type of service */
+ PACK_STRUCT_FIELD(u8_t _tos);
+ /* total length */
+ PACK_STRUCT_FIELD(u16_t _len);
+ /* identification */
+ PACK_STRUCT_FIELD(u16_t _id);
+ /* fragment offset field */
+ PACK_STRUCT_FIELD(u16_t _offset);
+#define IP_RF 0x8000U /* reserved fragment flag */
+#define IP_DF 0x4000U /* dont fragment flag */
+#define IP_MF 0x2000U /* more fragments flag */
+#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */
+ /* time to live */
+ PACK_STRUCT_FIELD(u8_t _ttl);
+ /* protocol*/
+ PACK_STRUCT_FIELD(u8_t _proto);
+ /* checksum */
+ PACK_STRUCT_FIELD(u16_t _chksum);
+ /* source and destination IP addresses */
+ PACK_STRUCT_FIELD(ip_addr_p_t src);
+ PACK_STRUCT_FIELD(ip_addr_p_t dest);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define IPH_V(hdr) ((hdr)->_v_hl >> 4)
+#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f)
+#define IPH_TOS(hdr) ((hdr)->_tos)
+#define IPH_LEN(hdr) ((hdr)->_len)
+#define IPH_ID(hdr) ((hdr)->_id)
+#define IPH_OFFSET(hdr) ((hdr)->_offset)
+#define IPH_TTL(hdr) ((hdr)->_ttl)
+#define IPH_PROTO(hdr) ((hdr)->_proto)
+#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
+
+#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl))
+#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos)
+#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
+#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
+#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
+#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl)
+#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto)
+#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
+
+#define IP_HLEN 20
+
+#define IP_PROTO_ICMP 1
+#define IP_PROTO_IGMP 2
+#define IP_PROTO_UDP 17
+#define IP_PROTO_UDPLITE 136
+#define IP_PROTO_TCP 6
+
+PACK_STRUCT_BEGIN
+struct udp_hdr {
+ PACK_STRUCT_FIELD(u16_t src);
+ PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */
+ PACK_STRUCT_FIELD(u16_t len);
+ PACK_STRUCT_FIELD(u16_t chksum);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+PACK_STRUCT_BEGIN
+struct tcp_hdr {
+ PACK_STRUCT_FIELD(u16_t src);
+ PACK_STRUCT_FIELD(u16_t dest);
+ PACK_STRUCT_FIELD(u32_t seqno);
+ PACK_STRUCT_FIELD(u32_t ackno);
+ PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
+ PACK_STRUCT_FIELD(u16_t wnd);
+ PACK_STRUCT_FIELD(u16_t chksum);
+ PACK_STRUCT_FIELD(u16_t urgp);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define TCP_FIN 0x01U
+#define TCP_SYN 0x02U
+#define TCP_RST 0x04U
+#define TCP_PSH 0x08U
+#define TCP_ACK 0x10U
+#define TCP_URG 0x20U
+#define TCP_ECE 0x40U
+#define TCP_CWR 0x80U
+
+#define TCP_FLAGS 0x3fU
+
+/* Length of the TCP header, excluding options. */
+#define TCP_HLEN 20
+
+#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
+#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
+
+#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
+#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
+#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags))
+
+#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
+#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
+
+#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
+
+/** This returns a TCP header option for MSS in an u32_t */
+#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF))
+
+void lwip_mutex_lock(void);
+void lwip_mutex_unlock(void);
+
+// XXX: These assume a little-endian system!
+/* These macros should be calculated by the preprocessor and are used
+ with compile-time constants only (so that there is no little-endian
+ overhead at runtime). */
+#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+#define PP_NTOHS(x) PP_HTONS(x)
+#define PP_HTONL(x) ((((x) & 0xff) << 24) | \
+ (((x) & 0xff00) << 8) | \
+ (((x) & 0xff0000UL) >> 8) | \
+ (((x) & 0xff000000UL) >> 24))
+#define PP_NTOHL(x) PP_HTONL(x)
+
+#define lwip_htons(x) LWIP_PLATFORM_HTONS(x)
+#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x)
+#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x)
+#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x)
+
+#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif))
+u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif);
+
+#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr)
+u8_t ip4_addr_netmask_valid(u32_t netmask);
+
+u32_t ipaddr_addr(const char *cp);
+int ipaddr_aton(const char *cp, ip_addr_t *addr);
+/** returns ptr to static buffer; not reentrant! */
+char *ipaddr_ntoa(const ip_addr_t *addr);
+char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen);
+
+#endif
};
#endif // 0 DELETEME
+#define MAX_V2P_MAPPINGS 64
+
+struct v2pmap {
+ genvaddr_t va;
+ genpaddr_t pa;
+ size_t size;
+};
+
struct morecore_state {
struct thread_mutex mutex;
Header header_base;
Header *header_freep;
struct vspace_mmu_aware mmu_state;
+ struct v2pmap v2p_mappings[MAX_V2P_MAPPINGS];
+ int v2p_entries;
#if 0 // DELETEME
struct captrack track_frames[MAX_TRACK_FRAMES];
#endif // 0 DELETEME
struct monitor_binding;
struct mem_rpc_client;
struct spawn_rpc_client;
+struct arrakis_rpc_client;
struct core_state_generic {
struct waitset default_waitset;
struct ram_alloc_state ram_alloc_state;
struct octopus_rpc_client *octopus_rpc_client;
struct spawn_rpc_client *spawn_rpc_clients[MAX_CPUS];
+ struct arrakis_rpc_client *arrakis_rpc_clients[MAX_CPUS];
struct terminal_state *terminal_state;
struct domain_state *domain_state;
struct spawn_state *spawn_state;
void debug_call_chain(arch_registers_state_t *state);
void debug_return_addresses(void);
void debug_dump_mem_around_addr(lvaddr_t addr);
-void debug_dump_mem(lvaddr_t base, lvaddr_t limit);
+void debug_dump_mem(lvaddr_t base, lvaddr_t limit, lvaddr_t point);
void debug_err(const char *file, const char *func, int line,
errval_t err, const char *msg, ...);
*/
/*
- * Copyright (c) 2009, 2011, ETH Zurich.
+ * Copyright (c) 2009, 2011, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
struct waitset *ws, delayus_t delay,
struct event_closure closure);
errval_t deferred_event_cancel(struct deferred_event *event);
+errval_t barrelfish_usleep(delayus_t delay);
struct periodic_event {
struct deferred_event de;
struct monitor_blocking_rpc_client;
struct waitset;
struct spawn_rpc_client;
+struct arrakis_rpc_client;
struct waitset *get_default_waitset(void);
void disp_set_core_id(coreid_t core_id);
void set_octopus_rpc_client(struct octopus_rpc_client *st);
struct octopus_rpc_client *get_octopus_rpc_client(void);
void set_spawn_rpc_client(coreid_t core, struct spawn_rpc_client *st);
+void set_arrakis_rpc_client(coreid_t core, struct arrakis_rpc_client *st);
struct spawn_rpc_client *get_spawn_rpc_client(coreid_t core);
+struct arrakis_rpc_client *get_arrakis_rpc_client(coreid_t core);
struct terminal_state *get_terminal_state(void);
void set_terminal_state(struct terminal_state *st);
struct domain_state *get_domain_state(void);
errval_t inthandler_setup_arm(interrupt_handler_fn handler, void *handler_arg,
uint32_t irq);
+extern struct waitset *barrelfish_interrupt_waitset;
+
__END_DECLS
#endif
genpaddr_t offset; ///< Offset into the frame
struct capref frame; ///< Capability of the frame
size_t size; ///< Size of the frame
+ genpaddr_t pa; ///< XXX: physical address of frame
struct memobj_frame_list *next;
};
struct capref inheritcn_cap,
struct capref argcn_cap, spawn_flags_t flags,
domainid_t *ret_domainid);
+errval_t spawn_arrakis_program(coreid_t coreid, const char *path,
+ char *const argv[], char *const envp[],
+ struct capref inheritcn_cap,
+ struct capref argcn_cap, spawn_flags_t flags,
+ domainid_t *ret_domainid);
errval_t spawn_program(coreid_t coreid, const char *path,
char *const argv[], char *const envp[],
spawn_flags_t flags, domainid_t *ret_domainid);
errval_t sys_debug_context_counter_read(uint64_t *ret);
errval_t sys_debug_timeslice_counter_read(uint64_t *ret);
errval_t sys_debug_get_tsc_per_ms(uint64_t *ret);
+errval_t sys_debug_get_apic_id(uint8_t *ret);
errval_t sys_debug_get_apic_timer(uint32_t *ret);
errval_t sys_debug_print_context_counter(void);
errval_t sys_debug_print_timeslice(void);
void thread_set_tls(void *);
void *thread_get_tls(void);
+void thread_set_tls_key(int, void *);
+void *thread_get_tls_key(int);
+
+uintptr_t thread_id(void);
+void thread_set_id(uintptr_t id);
+
__END_DECLS
#endif
struct event_closure closure);
void waitset_chan_migrate(struct waitset_chanstate *chan,
struct waitset *new_ws);
+errval_t waitset_chan_register_polled(struct waitset *ws,
+ struct waitset_chanstate *chan,
+ struct event_closure closure);
__END_DECLS
DEBUG_GET_TSC_PER_MS,
DEBUG_GET_APIC_TIMER,
DEBUG_GET_APIC_TICKS_PER_SEC,
- DEBUG_FEIGN_FRAME_CAP
+ DEBUG_FEIGN_FRAME_CAP,
+ DEBUG_GET_APIC_ID
};
#endif //BARRELFISH_KPI_SYS_DEBUG_H
char name[NAME_SIZE];
};
+// Utility functions
+uint64_t my_avg(uint64_t sum, uint64_t n);
+#ifndef LIBRARY
+
+float in_seconds(uint64_t cycles);
void netbench_reset(struct netbench_details *nbp);
struct netbench_details *netbench_alloc(char *name, uint32_t total_events);
uint8_t event_type, char *event_name, int type);
void netbench_print_all_stats(struct netbench_details *nbp);
-// Utility functions
-uint64_t my_avg(uint64_t sum, uint64_t n);
-float in_seconds(uint64_t cycles);
+#else
+
+#define netbench_reset(a)
+#define netbench_alloc(a, b)
+#define netbench_record_event(a, b, c)
+#define netbench_record_event_no_ts(a, b)
+#define netbench_record_event_simple(a, b, c) while(0) { (void)c; }
+#define netbench_print_event_stat(a, b, c, d)
+#define netbench_print_all_stats(a)
+
+static inline float in_seconds(uint64_t cycles)
+{
+ return cycles;
+}
+
+#endif
__END_DECLS
#define O_NOCTTY 00400
#define O_TRUNC 01000
#define O_APPEND 02000
+#ifndef O_NONBLOCK
#define O_NONBLOCK 04000
+#endif
#define O_SYNC 010000
#define O_FSYNC O_SYNC
#define O_ASYNC 020000
#define FFSYNC O_FSYNC /* kernel */
#define FNONBLOCK O_NONBLOCK /* kernel */
#define FNDELAY O_NONBLOCK /* compat */
+#ifndef O_NDELAY
#define O_NDELAY O_NONBLOCK /* compat */
#endif
+#endif
/*
* We are out of bits in f_flag (which is a short). However,
* $FreeBSD: src/sys/sys/limits.h,v 1.10 2005/12/02 07:45:28 davidxu Exp $
*/
-#ifndef _SYS_LIMITS_H_
-#define _SYS_LIMITS_H_
+#ifndef _LIMITS_H_
+#define _LIMITS_H_
#include <sys/cdefs.h>
#include <machine/_limits.h>
#undef ULONG_LONG_MAX
#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1ULL)
-// Barrelfish addition
-// I'm not sure where this belongs, but limits.h must provide it -AB
-#define PATH_MAX 1330
+#if __POSIX_VISIBLE
+#ifdef CONFIG_NEWLIB
+#include <sys/syslimits.h>
+#endif
+#endif
#endif /* !_SYS_LIMITS_H_ */
__BEGIN_DECLS
/*
+ * Error return codes from getaddrinfo()
+ */
+#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
+#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
+#define EAI_SYSTEM 11 /* system error returned in errno */
+#define EAI_BADHINTS 12 /* invalid value for hints */
+#define EAI_PROTOCOL 13 /* resolved protocol is unknown */
+#define EAI_OVERFLOW 14 /* argument buffer overflow */
+
+/*
* Flag values for getaddrinfo()
*/
#define AI_PASSIVE 0x00000001 /* get address to use bind() */
/* special recommended flags for getipnodebyname */
#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+/*
+ * Constants for getnameinfo()
+ */
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+/*
+ * Flag values for getnameinfo()
+ */
+#define NI_NOFQDN 0x00000001
+#define NI_NUMERICHOST 0x00000002
+#define NI_NAMEREQD 0x00000004
+#define NI_NUMERICSERV 0x00000008
+#define NI_DGRAM 0x00000010
+#if 0 /* obsolete */
+#define NI_WITHSCOPEID 0x00000020
+#endif
+
struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);
int getaddrinfo(const char *nodename,
typedef int_least16_t in_port_t;
typedef int_least32_t in_addr_t;
+#define IPPROTO_IPV6 41 /* IP6 header */
+#define INET_ADDRSTRLEN 16
+
/*
* Ports < IPPORT_RESERVED are reserved for
* privileged processes (e.g. root). (IP_PORTRANGE_LOW)
*/
#define IPPORT_RESERVED 1024
+/* INET6 stuff */
+#if __POSIX_VISIBLE >= 200112
+#define __KAME_NETINET_IN_H_INCLUDED_
+#include <netinet6/in6.h>
+#undef __KAME_NETINET_IN_H_INCLUDED_
+#endif
+
#endif //_NETINET_IN_H_
--- /dev/null
+/*-
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $KAME: in6.h,v 1.89 2001/05/27 13:28:35 itojun Exp $
+ */
+
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)in.h 8.3 (Berkeley) 1/3/94
+ * $FreeBSD$
+ */
+
+#ifndef __KAME_NETINET_IN_H_INCLUDED_
+#error "do not include netinet6/in6.h directly, include netinet/in.h. see RFC2553"
+#endif
+
+#ifndef _NETINET6_IN6_H_
+#define _NETINET6_IN6_H_
+
+/*
+ * Identification of the network protocol stack
+ * for *BSD-current/release: http://www.kame.net/dev/cvsweb.cgi/kame/COVERAGE
+ * has the table of implementation/integration differences.
+ */
+#define __KAME__
+#define __KAME_VERSION "FreeBSD"
+
+/*
+ * IPv6 port allocation rules should mirror the IPv4 rules and are controlled
+ * by the net.inet.ip.portrange sysctl tree. The following defines exist
+ * for compatibility with userland applications that need them.
+ */
+#if __BSD_VISIBLE
+#define IPV6PORT_RESERVED 1024
+#define IPV6PORT_ANONMIN 49152
+#define IPV6PORT_ANONMAX 65535
+#define IPV6PORT_RESERVEDMIN 600
+#define IPV6PORT_RESERVEDMAX (IPV6PORT_RESERVED-1)
+#endif
+
+/*
+ * IPv6 address
+ */
+struct in6_addr {
+ union {
+ uint8_t __u6_addr8[16];
+ uint16_t __u6_addr16[8];
+ uint32_t __u6_addr32[4];
+ } __u6_addr; /* 128-bit IP6 address */
+};
+
+#define s6_addr __u6_addr.__u6_addr8
+#ifdef _KERNEL /* XXX nonstandard */
+#define s6_addr8 __u6_addr.__u6_addr8
+#define s6_addr16 __u6_addr.__u6_addr16
+#define s6_addr32 __u6_addr.__u6_addr32
+#endif
+
+#define INET6_ADDRSTRLEN 46
+
+/*
+ * XXX missing POSIX.1-2001 macro IPPROTO_IPV6.
+ */
+
+/*
+ * Socket address for IPv6
+ */
+#if __BSD_VISIBLE
+#define SIN6_LEN
+#endif
+
+struct sockaddr_in6 {
+ uint8_t sin6_len; /* length of this struct */
+ sa_family_t sin6_family; /* AF_INET6 */
+ in_port_t sin6_port; /* Transport layer port # */
+ uint32_t sin6_flowinfo; /* IP6 flow information */
+ struct in6_addr sin6_addr; /* IP6 address */
+ uint32_t sin6_scope_id; /* scope zone index */
+};
+
+/*
+ * Local definition for masks
+ */
+#ifdef _KERNEL /* XXX nonstandard */
+#define IN6MASK0 {{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}}
+#define IN6MASK32 {{{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
+#define IN6MASK64 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
+#define IN6MASK96 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}
+#define IN6MASK128 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}
+#endif
+
+#ifdef _KERNEL
+extern const struct sockaddr_in6 sa6_any;
+
+extern const struct in6_addr in6mask0;
+extern const struct in6_addr in6mask32;
+extern const struct in6_addr in6mask64;
+extern const struct in6_addr in6mask96;
+extern const struct in6_addr in6mask128;
+#endif /* _KERNEL */
+
+/*
+ * Macros started with IPV6_ADDR is KAME local
+ */
+#ifdef _KERNEL /* XXX nonstandard */
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define IPV6_ADDR_INT32_ONE 1
+#define IPV6_ADDR_INT32_TWO 2
+#define IPV6_ADDR_INT32_MNL 0xff010000
+#define IPV6_ADDR_INT32_MLL 0xff020000
+#define IPV6_ADDR_INT32_SMP 0x0000ffff
+#define IPV6_ADDR_INT16_ULL 0xfe80
+#define IPV6_ADDR_INT16_USL 0xfec0
+#define IPV6_ADDR_INT16_MLL 0xff02
+#elif _BYTE_ORDER == _LITTLE_ENDIAN
+#define IPV6_ADDR_INT32_ONE 0x01000000
+#define IPV6_ADDR_INT32_TWO 0x02000000
+#define IPV6_ADDR_INT32_MNL 0x000001ff
+#define IPV6_ADDR_INT32_MLL 0x000002ff
+#define IPV6_ADDR_INT32_SMP 0xffff0000
+#define IPV6_ADDR_INT16_ULL 0x80fe
+#define IPV6_ADDR_INT16_USL 0xc0fe
+#define IPV6_ADDR_INT16_MLL 0x02ff
+#endif
+#endif
+
+/*
+ * Definition of some useful macros to handle IP6 addresses
+ */
+#if __BSD_VISIBLE
+#define IN6ADDR_ANY_INIT \
+ {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
+#define IN6ADDR_LOOPBACK_INIT \
+ {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
+#define IN6ADDR_NODELOCAL_ALLNODES_INIT \
+ {{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
+#define IN6ADDR_INTFACELOCAL_ALLNODES_INIT \
+ {{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
+#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \
+ {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
+#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
+ {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
+#define IN6ADDR_LINKLOCAL_ALLV2ROUTERS_INIT \
+ {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16 }}}
+#endif
+
+extern const struct in6_addr in6addr_any;
+extern const struct in6_addr in6addr_loopback;
+#if __BSD_VISIBLE
+extern const struct in6_addr in6addr_nodelocal_allnodes;
+extern const struct in6_addr in6addr_linklocal_allnodes;
+extern const struct in6_addr in6addr_linklocal_allrouters;
+extern const struct in6_addr in6addr_linklocal_allv2routers;
+#endif
+
+/*
+ * Equality
+ * NOTE: Some of kernel programming environment (for example, openbsd/sparc)
+ * does not supply memcmp(). For userland memcmp() is preferred as it is
+ * in ANSI standard.
+ */
+#ifdef _KERNEL
+#define IN6_ARE_ADDR_EQUAL(a, b) \
+ (bcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
+#else
+#if __BSD_VISIBLE
+#define IN6_ARE_ADDR_EQUAL(a, b) \
+ (memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
+#endif
+#endif
+
+/*
+ * Unspecified
+ */
+#define IN6_IS_ADDR_UNSPECIFIED(a) \
+ ((a)->__u6_addr.__u6_addr32[0] == 0 && \
+ (a)->__u6_addr.__u6_addr32[1] == 0 && \
+ (a)->__u6_addr.__u6_addr32[2] == 0 && \
+ (a)->__u6_addr.__u6_addr32[3] == 0)
+
+/*
+ * Loopback
+ */
+#define IN6_IS_ADDR_LOOPBACK(a) \
+ ((a)->__u6_addr.__u6_addr32[0] == 0 && \
+ (a)->__u6_addr.__u6_addr32[1] == 0 && \
+ (a)->__u6_addr.__u6_addr32[2] == 0 && \
+ (a)->__u6_addr.__u6_addr32[3] == ntohl(1))
+
+/*
+ * IPv4 compatible
+ */
+#define IN6_IS_ADDR_V4COMPAT(a) \
+ ((a)->__u6_addr.__u6_addr32[0] == 0 && \
+ (a)->__u6_addr.__u6_addr32[1] == 0 && \
+ (a)->__u6_addr.__u6_addr32[2] == 0 && \
+ (a)->__u6_addr.__u6_addr32[3] != 0 && \
+ (a)->__u6_addr.__u6_addr32[3] != ntohl(1))
+
+/*
+ * Mapped
+ */
+#define IN6_IS_ADDR_V4MAPPED(a) \
+ ((a)->__u6_addr.__u6_addr32[0] == 0 && \
+ (a)->__u6_addr.__u6_addr32[1] == 0 && \
+ (a)->__u6_addr.__u6_addr32[2] == ntohl(0x0000ffff))
+
+/*
+ * KAME Scope Values
+ */
+
+#ifdef _KERNEL /* XXX nonstandard */
+#define IPV6_ADDR_SCOPE_NODELOCAL 0x01
+#define IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
+#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02
+#define IPV6_ADDR_SCOPE_SITELOCAL 0x05
+#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */
+#define IPV6_ADDR_SCOPE_GLOBAL 0x0e
+#else
+#define __IPV6_ADDR_SCOPE_NODELOCAL 0x01
+#define __IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
+#define __IPV6_ADDR_SCOPE_LINKLOCAL 0x02
+#define __IPV6_ADDR_SCOPE_SITELOCAL 0x05
+#define __IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */
+#define __IPV6_ADDR_SCOPE_GLOBAL 0x0e
+#endif
+
+/*
+ * Unicast Scope
+ * Note that we must check topmost 10 bits only, not 16 bits (see RFC2373).
+ */
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+ (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
+#define IN6_IS_ADDR_SITELOCAL(a) \
+ (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
+
+/*
+ * Multicast
+ */
+#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff)
+
+#ifdef _KERNEL /* XXX nonstandard */
+#define IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f)
+#else
+#define __IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f)
+#endif
+
+/*
+ * Multicast Scope
+ */
+#ifdef _KERNEL /* refers nonstandard items */
+#define IN6_IS_ADDR_MC_NODELOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_NODELOCAL))
+#define IN6_IS_ADDR_MC_INTFACELOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_INTFACELOCAL))
+#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_LINKLOCAL))
+#define IN6_IS_ADDR_MC_SITELOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_SITELOCAL))
+#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_ORGLOCAL))
+#define IN6_IS_ADDR_MC_GLOBAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_GLOBAL))
+#else
+#define IN6_IS_ADDR_MC_NODELOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL))
+#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL))
+#define IN6_IS_ADDR_MC_SITELOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL))
+#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL))
+#define IN6_IS_ADDR_MC_GLOBAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL))
+#endif
+
+#ifdef _KERNEL /* nonstandard */
+/*
+ * KAME Scope
+ */
+#define IN6_IS_SCOPE_LINKLOCAL(a) \
+ ((IN6_IS_ADDR_LINKLOCAL(a)) || \
+ (IN6_IS_ADDR_MC_LINKLOCAL(a)))
+#define IN6_IS_SCOPE_EMBED(a) \
+ ((IN6_IS_ADDR_LINKLOCAL(a)) || \
+ (IN6_IS_ADDR_MC_LINKLOCAL(a)) || \
+ (IN6_IS_ADDR_MC_INTFACELOCAL(a)))
+
+#define IFA6_IS_DEPRECATED(a) \
+ ((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \
+ (u_int32_t)((time_second - (a)->ia6_updatetime)) > \
+ (a)->ia6_lifetime.ia6t_pltime)
+#define IFA6_IS_INVALID(a) \
+ ((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \
+ (u_int32_t)((time_second - (a)->ia6_updatetime)) > \
+ (a)->ia6_lifetime.ia6t_vltime)
+#endif /* _KERNEL */
+
+/*
+ * IP6 route structure
+ */
+#if __BSD_VISIBLE
+struct route_in6 {
+ struct rtentry *ro_rt;
+ struct llentry *ro_lle;
+ struct in6_addr *ro_ia6;
+ int ro_flags;
+ struct sockaddr_in6 ro_dst;
+};
+#endif
+
+/*
+ * Options for use with [gs]etsockopt at the IPV6 level.
+ * First word of comment is data type; bool is stored in int.
+ */
+/* no hdrincl */
+#if 0 /* the followings are relic in IPv4 and hence are disabled */
+#define IPV6_OPTIONS 1 /* buf/ip6_opts; set/get IP6 options */
+#define IPV6_RECVOPTS 5 /* bool; receive all IP6 opts w/dgram */
+#define IPV6_RECVRETOPTS 6 /* bool; receive IP6 opts for response */
+#define IPV6_RECVDSTADDR 7 /* bool; receive IP6 dst addr w/dgram */
+#define IPV6_RETOPTS 8 /* ip6_opts; set/get IP6 options */
+#endif
+#define IPV6_SOCKOPT_RESERVED1 3 /* reserved for future use */
+#define IPV6_UNICAST_HOPS 4 /* int; IP6 hops */
+#define IPV6_MULTICAST_IF 9 /* u_int; set/get IP6 multicast i/f */
+#define IPV6_MULTICAST_HOPS 10 /* int; set/get IP6 multicast hops */
+#define IPV6_MULTICAST_LOOP 11 /* u_int; set/get IP6 multicast loopback */
+#define IPV6_JOIN_GROUP 12 /* ipv6_mreq; join a group membership */
+#define IPV6_LEAVE_GROUP 13 /* ipv6_mreq; leave a group membership */
+#define IPV6_PORTRANGE 14 /* int; range to choose for unspec port */
+#define ICMP6_FILTER 18 /* icmp6_filter; icmp6 filter */
+/* RFC2292 options */
+#ifdef _KERNEL
+#define IPV6_2292PKTINFO 19 /* bool; send/recv if, src/dst addr */
+#define IPV6_2292HOPLIMIT 20 /* bool; hop limit */
+#define IPV6_2292NEXTHOP 21 /* bool; next hop addr */
+#define IPV6_2292HOPOPTS 22 /* bool; hop-by-hop option */
+#define IPV6_2292DSTOPTS 23 /* bool; destinaion option */
+#define IPV6_2292RTHDR 24 /* bool; routing header */
+#define IPV6_2292PKTOPTIONS 25 /* buf/cmsghdr; set/get IPv6 options */
+#endif
+
+#define IPV6_CHECKSUM 26 /* int; checksum offset for raw socket */
+#define IPV6_V6ONLY 27 /* bool; make AF_INET6 sockets v6 only */
+#ifndef _KERNEL
+#define IPV6_BINDV6ONLY IPV6_V6ONLY
+#endif
+
+#if 1 /* IPSEC */
+#define IPV6_IPSEC_POLICY 28 /* struct; get/set security policy */
+#endif /* IPSEC */
+
+#define IPV6_FAITH 29 /* bool; accept FAITH'ed connections */
+
+#if 1 /* IPV6FIREWALL */
+#define IPV6_FW_ADD 30 /* add a firewall rule to chain */
+#define IPV6_FW_DEL 31 /* delete a firewall rule from chain */
+#define IPV6_FW_FLUSH 32 /* flush firewall rule chain */
+#define IPV6_FW_ZERO 33 /* clear single/all firewall counter(s) */
+#define IPV6_FW_GET 34 /* get entire firewall rule chain */
+#endif
+
+/* new socket options introduced in RFC3542 */
+#define IPV6_RTHDRDSTOPTS 35 /* ip6_dest; send dst option before rthdr */
+
+#define IPV6_RECVPKTINFO 36 /* bool; recv if, dst addr */
+#define IPV6_RECVHOPLIMIT 37 /* bool; recv hop limit */
+#define IPV6_RECVRTHDR 38 /* bool; recv routing header */
+#define IPV6_RECVHOPOPTS 39 /* bool; recv hop-by-hop option */
+#define IPV6_RECVDSTOPTS 40 /* bool; recv dst option after rthdr */
+#ifdef _KERNEL
+#define IPV6_RECVRTHDRDSTOPTS 41 /* bool; recv dst option before rthdr */
+#endif
+
+#define IPV6_USE_MIN_MTU 42 /* bool; send packets at the minimum MTU */
+#define IPV6_RECVPATHMTU 43 /* bool; notify an according MTU */
+
+#define IPV6_PATHMTU 44 /* mtuinfo; get the current path MTU (sopt),
+ 4 bytes int; MTU notification (cmsg) */
+#if 0 /*obsoleted during 2292bis -> 3542*/
+#define IPV6_REACHCONF 45 /* no data; ND reachability confirm
+ (cmsg only/not in of RFC3542) */
+#endif
+
+/* more new socket options introduced in RFC3542 */
+#define IPV6_PKTINFO 46 /* in6_pktinfo; send if, src addr */
+#define IPV6_HOPLIMIT 47 /* int; send hop limit */
+#define IPV6_NEXTHOP 48 /* sockaddr; next hop addr */
+#define IPV6_HOPOPTS 49 /* ip6_hbh; send hop-by-hop option */
+#define IPV6_DSTOPTS 50 /* ip6_dest; send dst option befor rthdr */
+#define IPV6_RTHDR 51 /* ip6_rthdr; send routing header */
+#if 0
+#define IPV6_PKTOPTIONS 52 /* buf/cmsghdr; set/get IPv6 options */
+ /* obsoleted by RFC3542 */
+#endif
+
+#define IPV6_RECVTCLASS 57 /* bool; recv traffic class values */
+
+#define IPV6_AUTOFLOWLABEL 59 /* bool; attach flowlabel automagically */
+
+#define IPV6_TCLASS 61 /* int; send traffic class value */
+#define IPV6_DONTFRAG 62 /* bool; disable IPv6 fragmentation */
+
+#define IPV6_PREFER_TEMPADDR 63 /* int; prefer temporary addresses as
+ * the source address.
+ */
+
+#define IPV6_BINDANY 64 /* bool: allow bind to any address */
+
+/*
+ * The following option is private; do not use it from user applications.
+ * It is deliberately defined to the same value as IP_MSFILTER.
+ */
+#define IPV6_MSFILTER 74 /* struct __msfilterreq;
+ * set/get multicast source filter list.
+ */
+
+/* to define items, should talk with KAME guys first, for *BSD compatibility */
+
+#define IPV6_RTHDR_LOOSE 0 /* this hop need not be a neighbor. XXX old spec */
+#define IPV6_RTHDR_STRICT 1 /* this hop must be a neighbor. XXX old spec */
+#define IPV6_RTHDR_TYPE_0 0 /* IPv6 routing header type 0 */
+
+/*
+ * Defaults and limits for options
+ */
+#define IPV6_DEFAULT_MULTICAST_HOPS 1 /* normally limit m'casts to 1 hop */
+#define IPV6_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
+
+/*
+ * The im6o_membership vector for each socket is now dynamically allocated at
+ * run-time, bounded by USHRT_MAX, and is reallocated when needed, sized
+ * according to a power-of-two increment.
+ */
+#define IPV6_MIN_MEMBERSHIPS 31
+#define IPV6_MAX_MEMBERSHIPS 4095
+
+/*
+ * Default resource limits for IPv6 multicast source filtering.
+ * These may be modified by sysctl.
+ */
+#define IPV6_MAX_GROUP_SRC_FILTER 512 /* sources per group */
+#define IPV6_MAX_SOCK_SRC_FILTER 128 /* sources per socket/group */
+
+/*
+ * Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP.
+ */
+struct ipv6_mreq {
+ struct in6_addr ipv6mr_multiaddr;
+ unsigned int ipv6mr_interface;
+};
+
+/*
+ * IPV6_PKTINFO: Packet information(RFC2292 sec 5)
+ */
+struct in6_pktinfo {
+ struct in6_addr ipi6_addr; /* src/dst IPv6 address */
+ unsigned int ipi6_ifindex; /* send/recv interface index */
+};
+
+/*
+ * Control structure for IPV6_RECVPATHMTU socket option.
+ */
+struct ip6_mtuinfo {
+ struct sockaddr_in6 ip6m_addr; /* or sockaddr_storage? */
+ uint32_t ip6m_mtu;
+};
+
+/*
+ * Argument for IPV6_PORTRANGE:
+ * - which range to search when port is unspecified at bind() or connect()
+ */
+#define IPV6_PORTRANGE_DEFAULT 0 /* default range */
+#define IPV6_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */
+#define IPV6_PORTRANGE_LOW 2 /* "low" - vouchsafe security */
+
+#if __BSD_VISIBLE
+/*
+ * Definitions for inet6 sysctl operations.
+ *
+ * Third level is protocol number.
+ * Fourth level is desired variable within that protocol.
+ */
+#define IPV6PROTO_MAXID (IPPROTO_PIM + 1) /* don't list to IPV6PROTO_MAX */
+
+/*
+ * Names for IP sysctl objects
+ */
+#define IPV6CTL_FORWARDING 1 /* act as router */
+#define IPV6CTL_SENDREDIRECTS 2 /* may send redirects when forwarding*/
+#define IPV6CTL_DEFHLIM 3 /* default Hop-Limit */
+#ifdef notyet
+#define IPV6CTL_DEFMTU 4 /* default MTU */
+#endif
+#define IPV6CTL_FORWSRCRT 5 /* forward source-routed dgrams */
+#define IPV6CTL_STATS 6 /* stats */
+#define IPV6CTL_MRTSTATS 7 /* multicast forwarding stats */
+#define IPV6CTL_MRTPROTO 8 /* multicast routing protocol */
+#define IPV6CTL_MAXFRAGPACKETS 9 /* max packets reassembly queue */
+#define IPV6CTL_SOURCECHECK 10 /* verify source route and intf */
+#define IPV6CTL_SOURCECHECK_LOGINT 11 /* minimume logging interval */
+#define IPV6CTL_ACCEPT_RTADV 12
+#define IPV6CTL_KEEPFAITH 13
+#define IPV6CTL_LOG_INTERVAL 14
+#define IPV6CTL_HDRNESTLIMIT 15
+#define IPV6CTL_DAD_COUNT 16
+#define IPV6CTL_AUTO_FLOWLABEL 17
+#define IPV6CTL_DEFMCASTHLIM 18
+#define IPV6CTL_GIF_HLIM 19 /* default HLIM for gif encap packet */
+#define IPV6CTL_KAME_VERSION 20
+#define IPV6CTL_USE_DEPRECATED 21 /* use deprecated addr (RFC2462 5.5.4) */
+#define IPV6CTL_RR_PRUNE 22 /* walk timer for router renumbering */
+#if 0 /* obsolete */
+#define IPV6CTL_MAPPED_ADDR 23
+#endif
+#define IPV6CTL_V6ONLY 24
+#define IPV6CTL_RTEXPIRE 25 /* cloned route expiration time */
+#define IPV6CTL_RTMINEXPIRE 26 /* min value for expiration time */
+#define IPV6CTL_RTMAXCACHE 27 /* trigger level for dynamic expire */
+
+#define IPV6CTL_USETEMPADDR 32 /* use temporary addresses (RFC3041) */
+#define IPV6CTL_TEMPPLTIME 33 /* preferred lifetime for tmpaddrs */
+#define IPV6CTL_TEMPVLTIME 34 /* valid lifetime for tmpaddrs */
+#define IPV6CTL_AUTO_LINKLOCAL 35 /* automatic link-local addr assign */
+#define IPV6CTL_RIP6STATS 36 /* raw_ip6 stats */
+#define IPV6CTL_PREFER_TEMPADDR 37 /* prefer temporary addr as src */
+#define IPV6CTL_ADDRCTLPOLICY 38 /* get/set address selection policy */
+#define IPV6CTL_USE_DEFAULTZONE 39 /* use default scope zone */
+
+#define IPV6CTL_MAXFRAGS 41 /* max fragments */
+#if 0
+#define IPV6CTL_IFQ 42 /* ip6intrq node */
+#define IPV6CTL_ISATAPRTR 43 /* isatap router */
+#endif
+#define IPV6CTL_MCAST_PMTU 44 /* enable pMTU discovery for multicast? */
+
+/* New entries should be added here from current IPV6CTL_MAXID value. */
+/* to define items, should talk with KAME guys first, for *BSD compatibility */
+#define IPV6CTL_STEALTH 45
+
+#define ICMPV6CTL_ND6_ONLINKNSRFC4861 47
+#define IPV6CTL_NO_RADR 48 /* No defroute from RA */
+#define IPV6CTL_NORBIT_RAIF 49 /* Disable R-bit in NA on RA
+ * receiving IF. */
+#define IPV6CTL_RFC6204W3 50 /* Accept defroute even when forwarding
+ enabled */
+#define IPV6CTL_MAXID 51
+#endif /* __BSD_VISIBLE */
+
+/*
+ * Redefinition of mbuf flags
+ */
+#define M_AUTHIPHDR M_PROTO2
+#define M_DECRYPTED M_PROTO3
+#define M_LOOP M_PROTO4
+#define M_AUTHIPDGM M_PROTO5
+#define M_RTALERT_MLD M_PROTO6
+
+#ifdef _KERNEL
+struct cmsghdr;
+
+int in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t));
+int in6_localaddr __P((struct in6_addr *));
+int in6_localip(struct in6_addr *);
+int in6_addrscope __P((struct in6_addr *));
+struct in6_ifaddr *in6_ifawithifp __P((struct ifnet *, struct in6_addr *));
+extern void in6_if_up __P((struct ifnet *));
+struct sockaddr;
+extern u_char ip6_protox[];
+
+void in6_sin6_2_sin __P((struct sockaddr_in *sin,
+ struct sockaddr_in6 *sin6));
+void in6_sin_2_v4mapsin6 __P((struct sockaddr_in *sin,
+ struct sockaddr_in6 *sin6));
+void in6_sin6_2_sin_in_sock __P((struct sockaddr *nam));
+void in6_sin_2_v4mapsin6_in_sock __P((struct sockaddr **nam));
+extern void addrsel_policy_init __P((void));
+
+#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
+#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
+#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
+
+extern int (*faithprefix_p)(struct in6_addr *);
+#endif /* _KERNEL */
+
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#define _SIZE_T_DECLARED
+#endif
+
+#ifndef _SOCKLEN_T_DECLARED
+typedef __socklen_t socklen_t;
+#define _SOCKLEN_T_DECLARED
+#endif
+
+#if __BSD_VISIBLE
+
+__BEGIN_DECLS
+struct cmsghdr;
+
+extern int inet6_option_space __P((int));
+extern int inet6_option_init __P((void *, struct cmsghdr **, int));
+extern int inet6_option_append __P((struct cmsghdr *, const uint8_t *,
+ int, int));
+extern uint8_t *inet6_option_alloc __P((struct cmsghdr *, int, int, int));
+extern int inet6_option_next __P((const struct cmsghdr *, uint8_t **));
+extern int inet6_option_find __P((const struct cmsghdr *, uint8_t **, int));
+
+extern size_t inet6_rthdr_space __P((int, int));
+extern struct cmsghdr *inet6_rthdr_init __P((void *, int));
+extern int inet6_rthdr_add __P((struct cmsghdr *, const struct in6_addr *,
+ unsigned int));
+extern int inet6_rthdr_lasthop __P((struct cmsghdr *, unsigned int));
+#if 0 /* not implemented yet */
+extern int inet6_rthdr_reverse __P((const struct cmsghdr *, struct cmsghdr *));
+#endif
+extern int inet6_rthdr_segments __P((const struct cmsghdr *));
+extern struct in6_addr *inet6_rthdr_getaddr __P((struct cmsghdr *, int));
+extern int inet6_rthdr_getflags __P((const struct cmsghdr *, int));
+
+extern int inet6_opt_init __P((void *, socklen_t));
+extern int inet6_opt_append __P((void *, socklen_t, int, uint8_t, socklen_t,
+ uint8_t, void **));
+extern int inet6_opt_finish __P((void *, socklen_t, int));
+extern int inet6_opt_set_val __P((void *, int, void *, socklen_t));
+
+extern int inet6_opt_next __P((void *, socklen_t, int, uint8_t *, socklen_t *,
+ void **));
+extern int inet6_opt_find __P((void *, socklen_t, int, uint8_t, socklen_t *,
+ void **));
+extern int inet6_opt_get_val __P((void *, int, void *, socklen_t));
+extern socklen_t inet6_rth_space __P((int, int));
+extern void *inet6_rth_init __P((void *, socklen_t, int, int));
+extern int inet6_rth_add __P((void *, const struct in6_addr *));
+extern int inet6_rth_reverse __P((const void *, void *));
+extern int inet6_rth_segments __P((const void *));
+extern struct in6_addr *inet6_rth_getaddr __P((const void *, int));
+__END_DECLS
+
+#endif /* __BSD_VISIBLE */
+
+#endif /* !_NETINET6_IN6_H_ */
--- /dev/null
+/*
+ * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
+ * Copyright (c) 1995-1998 by John Birrell <jb@cimlogic.com.au>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Chris Provenzano.
+ * 4. The name of Chris Provenzano may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _PTHREAD_H_
+#define _PTHREAD_H_
+
+/*
+ * Header files.
+ */
+#include <sys/cdefs.h>
+#include <sys/_pthreadtypes.h>
+#include <machine/_limits.h>
+#include <sys/_types.h>
+#include <sys/_sigset.h>
+#include <sys/types.h>
+#include <sched.h>
+#include <time.h>
+
+/*
+ * Run-time invariant values:
+ */
+#define PTHREAD_DESTRUCTOR_ITERATIONS 4
+#define PTHREAD_KEYS_MAX 256
+#define PTHREAD_STACK_MIN __MINSIGSTKSZ
+#define PTHREAD_THREADS_MAX __ULONG_MAX
+#define PTHREAD_BARRIER_SERIAL_THREAD -1
+
+/*
+ * Flags for threads and thread attributes.
+ */
+#define PTHREAD_DETACHED 0x1
+#define PTHREAD_SCOPE_SYSTEM 0x2
+#define PTHREAD_INHERIT_SCHED 0x4
+#define PTHREAD_NOFLOAT 0x8
+
+#define PTHREAD_CREATE_DETACHED PTHREAD_DETACHED
+#define PTHREAD_CREATE_JOINABLE 0
+#define PTHREAD_SCOPE_PROCESS 0
+#define PTHREAD_EXPLICIT_SCHED 0
+
+/*
+ * Flags for read/write lock attributes
+ */
+#define PTHREAD_PROCESS_PRIVATE 0
+#define PTHREAD_PROCESS_SHARED 1
+
+/*
+ * Flags for cancelling threads
+ */
+#define PTHREAD_CANCEL_ENABLE 0
+#define PTHREAD_CANCEL_DISABLE 1
+#define PTHREAD_CANCEL_DEFERRED 0
+#define PTHREAD_CANCEL_ASYNCHRONOUS 2
+#define PTHREAD_CANCELED ((void *) 1)
+
+/*
+ * Flags for once initialization.
+ */
+#define PTHREAD_NEEDS_INIT 0
+#define PTHREAD_DONE_INIT 1
+
+/*
+ * Static once initialization values.
+ */
+#define PTHREAD_ONCE_INIT { PTHREAD_NEEDS_INIT, NULL }
+
+/*
+ * Static initialization values.
+ */
+#define PTHREAD_MUTEX_INITIALIZER NULL
+#define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP ((pthread_mutex_t)1)
+#define PTHREAD_COND_INITIALIZER NULL
+#define PTHREAD_RWLOCK_INITIALIZER NULL
+
+/*
+ * Default attribute arguments (draft 4, deprecated).
+ */
+#ifndef PTHREAD_KERNEL
+#define pthread_condattr_default NULL
+#define pthread_mutexattr_default NULL
+#define pthread_attr_default NULL
+#endif
+
+#define PTHREAD_PRIO_NONE 0
+#define PTHREAD_PRIO_INHERIT 1
+#define PTHREAD_PRIO_PROTECT 2
+
+/*
+ * Mutex types (Single UNIX Specification, Version 2, 1997).
+ *
+ * Note that a mutex attribute with one of the following types:
+ *
+ * PTHREAD_MUTEX_NORMAL
+ * PTHREAD_MUTEX_RECURSIVE
+ *
+ * will deviate from POSIX specified semantics.
+ */
+enum pthread_mutextype {
+ PTHREAD_MUTEX_ERRORCHECK = 1, /* Default POSIX mutex */
+ PTHREAD_MUTEX_RECURSIVE = 2, /* Recursive mutex */
+ PTHREAD_MUTEX_NORMAL = 3, /* No error checking */
+ PTHREAD_MUTEX_ADAPTIVE_NP = 4, /* Adaptive mutex, spins briefly before blocking on lock */
+ PTHREAD_MUTEX_TYPE_MAX
+};
+
+#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_ERRORCHECK
+
+struct _pthread_cleanup_info {
+ __uintptr_t pthread_cleanup_pad[8];
+};
+
+/*
+ * Thread function prototype definitions:
+ */
+__BEGIN_DECLS
+int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
+int pthread_attr_destroy(pthread_attr_t *);
+int pthread_attr_getstack(const pthread_attr_t * __restrict,
+ void ** __restrict, size_t * __restrict);
+int pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
+int pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
+int pthread_attr_getstackaddr(const pthread_attr_t *, void **);
+int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
+int pthread_attr_init(pthread_attr_t *);
+int pthread_attr_setstacksize(pthread_attr_t *, size_t);
+int pthread_attr_setguardsize(pthread_attr_t *, size_t);
+int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
+int pthread_attr_setstackaddr(pthread_attr_t *, void *);
+int pthread_attr_setdetachstate(pthread_attr_t *, int);
+int pthread_barrier_destroy(pthread_barrier_t *);
+int pthread_barrier_init(pthread_barrier_t *,
+ const pthread_barrierattr_t *, unsigned);
+int pthread_barrier_wait(pthread_barrier_t *);
+int pthread_barrierattr_destroy(pthread_barrierattr_t *);
+int pthread_barrierattr_getpshared(const pthread_barrierattr_t *,
+ int *);
+int pthread_barrierattr_init(pthread_barrierattr_t *);
+int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
+
+#define pthread_cleanup_push(cleanup_routine, cleanup_arg) \
+ { \
+ struct _pthread_cleanup_info __cleanup_info__; \
+ __pthread_cleanup_push_imp(cleanup_routine, cleanup_arg,\
+ &__cleanup_info__); \
+ {
+
+#define pthread_cleanup_pop(execute) \
+ } \
+ __pthread_cleanup_pop_imp(execute); \
+ }
+
+int pthread_condattr_destroy(pthread_condattr_t *);
+int pthread_condattr_getclock(const pthread_condattr_t *,
+ clockid_t *);
+int pthread_condattr_getpshared(const pthread_condattr_t *, int *);
+int pthread_condattr_init(pthread_condattr_t *);
+int pthread_condattr_setclock(pthread_condattr_t *, clockid_t);
+int pthread_condattr_setpshared(pthread_condattr_t *, int);
+int pthread_cond_broadcast(pthread_cond_t *);
+int pthread_cond_destroy(pthread_cond_t *);
+int pthread_cond_init(pthread_cond_t *,
+ const pthread_condattr_t *);
+int pthread_cond_signal(pthread_cond_t *);
+int pthread_cond_timedwait(pthread_cond_t *,
+ pthread_mutex_t *, const struct timespec *);
+int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
+int pthread_create(pthread_t *, const pthread_attr_t *,
+ void *(*) (void *), void *);
+int pthread_detach(pthread_t);
+int pthread_equal(pthread_t, pthread_t);
+void pthread_exit(void *) __dead2;
+void *pthread_getspecific(pthread_key_t);
+int pthread_getcpuclockid(pthread_t, clockid_t *);
+int pthread_join(pthread_t, void **);
+int pthread_key_create(pthread_key_t *,
+ void (*) (void *));
+int pthread_key_delete(pthread_key_t);
+int pthread_mutexattr_init(pthread_mutexattr_t *);
+int pthread_mutexattr_destroy(pthread_mutexattr_t *);
+int pthread_mutexattr_getpshared(const pthread_mutexattr_t *,
+ int *);
+int pthread_mutexattr_gettype(pthread_mutexattr_t *, int *);
+int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
+int pthread_mutex_destroy(pthread_mutex_t *);
+int pthread_mutex_init(pthread_mutex_t *,
+ const pthread_mutexattr_t *);
+int pthread_mutex_lock(pthread_mutex_t *);
+int pthread_mutex_trylock(pthread_mutex_t *);
+int pthread_mutex_timedlock(pthread_mutex_t *,
+ const struct timespec *);
+int pthread_mutex_unlock(pthread_mutex_t *);
+int pthread_once(pthread_once_t *, void (*) (void));
+int pthread_rwlock_destroy(pthread_rwlock_t *);
+int pthread_rwlock_init(pthread_rwlock_t *,
+ const pthread_rwlockattr_t *);
+int pthread_rwlock_rdlock(pthread_rwlock_t *);
+int pthread_rwlock_timedrdlock(pthread_rwlock_t *,
+ const struct timespec *);
+int pthread_rwlock_timedwrlock(pthread_rwlock_t *,
+ const struct timespec *);
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+int pthread_rwlock_trywrlock(pthread_rwlock_t *);
+int pthread_rwlock_unlock(pthread_rwlock_t *);
+int pthread_rwlock_wrlock(pthread_rwlock_t *);
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
+int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *,
+ int *);
+int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *,
+ int *);
+int pthread_rwlockattr_init(pthread_rwlockattr_t *);
+int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int);
+int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
+pthread_t pthread_self(void);
+int pthread_setspecific(pthread_key_t, const void *);
+
+int pthread_spin_init(pthread_spinlock_t *, int);
+int pthread_spin_destroy(pthread_spinlock_t *);
+int pthread_spin_lock(pthread_spinlock_t *);
+int pthread_spin_trylock(pthread_spinlock_t *);
+int pthread_spin_unlock(pthread_spinlock_t *);
+int pthread_cancel(pthread_t);
+int pthread_setcancelstate(int, int *);
+int pthread_setcanceltype(int, int *);
+void pthread_testcancel(void);
+
+#if __BSD_VISIBLE
+int pthread_getprio(pthread_t);
+int pthread_setprio(pthread_t, int);
+void pthread_yield(void);
+#endif
+
+int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *,
+ int *);
+int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *,
+ int);
+int pthread_mutex_getprioceiling(pthread_mutex_t *, int *);
+int pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *);
+
+int pthread_mutexattr_getprotocol(pthread_mutexattr_t *, int *);
+int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
+
+int pthread_attr_getinheritsched(const pthread_attr_t *, int *);
+int pthread_attr_getschedparam(const pthread_attr_t *,
+ struct sched_param *);
+int pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
+int pthread_attr_getscope(const pthread_attr_t *, int *);
+int pthread_attr_setinheritsched(pthread_attr_t *, int);
+int pthread_attr_setschedparam(pthread_attr_t *,
+ const struct sched_param *);
+int pthread_attr_setschedpolicy(pthread_attr_t *, int);
+int pthread_attr_setscope(pthread_attr_t *, int);
+int pthread_getschedparam(pthread_t pthread, int *,
+ struct sched_param *);
+int pthread_setschedparam(pthread_t, int,
+ const struct sched_param *);
+#if __XSI_VISIBLE
+int pthread_getconcurrency(void);
+int pthread_setconcurrency(int);
+#endif
+
+void __pthread_cleanup_push_imp(void (*)(void *), void *,
+ struct _pthread_cleanup_info *);
+void __pthread_cleanup_pop_imp(int);
+__END_DECLS
+
+#endif
#define NSIG 32 /* number of old signals (counting 0) */
-#define SIG_ERR ((void *) -1)
-#define SIG_DFL ((void *) 0)
-#define SIG_IGN ((void *) 1)
-#define SIG_HOLD ((void *)3)
+#if __POSIX_VISIBLE || __XSI_VISIBLE
+#define SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
+#endif /* __POSIX_VISIBLE || __XSI_VISIBLE */
+
+#if __XSI_VISIBLE
+#define SA_ONSTACK 0x0001 /* take signal on signal stack */
+#define SA_RESTART 0x0002 /* restart system call on signal return */
+#define SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
+#define SA_NODEFER 0x0010 /* don't mask the signal we're delivering */
+#define SA_NOCLDWAIT 0x0020 /* don't keep zombies around */
+#define SA_SIGINFO 0x0040 /* signal handler with SA_SIGINFO args */
+#endif
+
+/* Adjusted to linux, has unused sa_restorer field and unsigned long
+ sa_flags; relatively unimportant though. */
+/* Type of a signal handler. */
+typedef void (*__sighandler_t)(int);
+
+/* The type used in newlib sources. */
+typedef __sighandler_t _sig_func_ptr;
+
+#define SIG_ERR ((_sig_func_ptr) -1)
+#define SIG_DFL ((_sig_func_ptr) 0)
+#define SIG_IGN ((_sig_func_ptr) 1)
+#define SIG_HOLD ((_sig_func_ptr)3)
#ifndef _PID_T_DECLARED
typedef __pid_t pid_t;
typedef __sigset_t sigset_t;
#endif
+union sigval {
+ /* Members as suggested by Annex C of POSIX 1003.1b. */
+ int sival_int;
+ void *sival_ptr;
+ /* 6.0 compatibility */
+ int sigval_int;
+ void *sigval_ptr;
+};
+
+typedef struct __siginfo {
+ int si_signo; /* signal number */
+ int si_errno; /* errno association */
+ /*
+ * Cause of signal, one of the SI_ macros or signal-specific
+ * values, i.e. one of the FPE_... values for SIGFPE. This
+ * value is equivalent to the second argument to an old-style
+ * FreeBSD signal handler.
+ */
+ int si_code; /* signal code */
+ __pid_t si_pid; /* sending process */
+ __uid_t si_uid; /* sender's ruid */
+ int si_status; /* exit value */
+ void *si_addr; /* faulting instruction */
+ union sigval si_value; /* signal value */
+ union {
+ struct {
+ int _trapno;/* machine specific trap code */
+ } _fault;
+ struct {
+ int _timerid;
+ int _overrun;
+ } _timer;
+ struct {
+ int _mqd;
+ } _mesgq;
+ struct {
+ long _band; /* band event for SIGPOLL */
+ } _poll; /* was this ever used ? */
+ struct {
+ long __spare1__;
+ int __spare2__[7];
+ } __spare__;
+ } _reason;
+} siginfo_t;
+
+#define si_trapno _reason._fault._trapno
+#define si_timerid _reason._timer._timerid
+#define si_overrun _reason._timer._overrun
+#define si_mqd _reason._mesgq._mqd
+#define si_band _reason._poll._band
+
+/* struct sigaction notes from POSIX:
+ *
+ * (1) Routines stored in sa_handler should take a single int as
+ * their argument although the POSIX standard does not require this.
+ * (2) The fields sa_handler and sa_sigaction may overlap, and a conforming
+ * application should not use both simultaneously.
+ */
+
+struct sigaction {
+ int sa_flags; /* Special flags to affect behavior of signal */
+ sigset_t sa_mask; /* Additional set of signals to be blocked */
+ /* during execution of signal-catching */
+ /* function. */
+ union {
+ _sig_func_ptr _handler; /* SIG_DFL, SIG_IGN, or pointer to a function */
+ void (*_sigaction)( int, siginfo_t *, void * );
+ } _signal_handlers;
+};
+
+#define sa_handler _signal_handlers._handler
+#define sa_sigaction _signal_handlers._sigaction
+
/*
* Flags for sigprocmask:
*/
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigismember(const sigset_t *set, int signo);
-
+int sigaction(int signum, const struct sigaction *act,
+ struct sigaction *oldact);
+int raise(int sig);
__END_DECLS
#endif // BARRELFISH_SIGNAL_H_
// vspace of spawned domain
struct vspace *vspace;
+ struct vregion *vregion[16];
+ genvaddr_t base[16];
+ unsigned int vregions;
dispatcher_handle_t handle;
enum cpu_type cpu_type;
struct iovec {
void *iov_base; /* Base address. */
size_t iov_len; /* Length. */
+ void *iov_opaque; /* XXX: Arranet extension. */
};
#endif /* !_SYS__IOVEC_H_ */
--- /dev/null
+/*
+ * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
+ * Copyright (c) 1995-1998 by John Birrell <jb@cimlogic.com.au>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Chris Provenzano.
+ * 4. The name of Chris Provenzano may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS__PTHREADTYPES_H_
+#define _SYS__PTHREADTYPES_H_
+
+/*
+ * Forward structure definitions.
+ *
+ * These are mostly opaque to the user.
+ */
+struct pthread;
+struct pthread_attr;
+struct pthread_cond;
+struct pthread_cond_attr;
+struct pthread_mutex;
+struct pthread_mutex_attr;
+struct pthread_once;
+struct pthread_rwlock;
+struct pthread_rwlockattr;
+struct pthread_barrier;
+struct pthread_barrier_attr;
+struct pthread_spinlock;
+
+/*
+ * Primitive system data type definitions required by P1003.1c.
+ *
+ * Note that P1003.1c specifies that there are no defined comparison
+ * or assignment operators for the types pthread_attr_t, pthread_cond_t,
+ * pthread_condattr_t, pthread_mutex_t, pthread_mutexattr_t.
+ */
+#ifndef _PTHREAD_T_DECLARED
+typedef struct pthread *pthread_t;
+#define _PTHREAD_T_DECLARED
+#endif
+typedef struct pthread_attr *pthread_attr_t;
+typedef struct pthread_mutex *pthread_mutex_t;
+typedef struct pthread_mutex_attr *pthread_mutexattr_t;
+typedef struct pthread_cond *pthread_cond_t;
+typedef struct pthread_cond_attr *pthread_condattr_t;
+typedef int pthread_key_t;
+typedef struct pthread_once pthread_once_t;
+typedef struct pthread_rwlock *pthread_rwlock_t;
+typedef struct pthread_rwlockattr *pthread_rwlockattr_t;
+typedef struct pthread_barrier *pthread_barrier_t;
+typedef struct pthread_barrierattr *pthread_barrierattr_t;
+typedef struct pthread_spinlock *pthread_spinlock_t;
+
+/*
+ * Additional type definitions:
+ *
+ * Note that P1003.1c reserves the prefixes pthread_ and PTHREAD_ for
+ * use in header symbols.
+ */
+typedef void *pthread_addr_t;
+typedef void *(*pthread_startroutine_t)(void *);
+
+/*
+ * Once definitions.
+ */
+struct pthread_once {
+ int state;
+ pthread_mutex_t mutex;
+};
+
+#endif /* ! _SYS__PTHREADTYPES_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 1982, 1985, 1986, 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)socket.h 8.4 (Berkeley) 2/21/94
+ * $FreeBSD$
+ */
+
+#ifndef _SYS__SOCKADDR_STORAGE_H_
+#define _SYS__SOCKADDR_STORAGE_H_
+
+/*
+ * RFC 2553: protocol-independent placeholder for socket addresses
+ */
+#define _SS_MAXSIZE 128U
+#define _SS_ALIGNSIZE (sizeof(__int64_t))
+#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) - \
+ sizeof(sa_family_t))
+#define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) - \
+ sizeof(sa_family_t) - _SS_PAD1SIZE - _SS_ALIGNSIZE)
+
+struct sockaddr_storage {
+ unsigned char ss_len; /* address length */
+ sa_family_t ss_family; /* address family */
+ char __ss_pad1[_SS_PAD1SIZE];
+ __int64_t __ss_align; /* force desired struct alignment */
+ char __ss_pad2[_SS_PAD2SIZE];
+};
+
+#endif /* !_SYS__SOCKADDR_STORAGE_H_ */
typedef int16_t __int16_t;
typedef int32_t __int32_t;
typedef int64_t __int64_t;
+typedef uintptr_t __uintptr_t;
typedef __uint8_t u_int8_t; /* unsigned integrals (deprecated) */
typedef __uint16_t u_int16_t;
typedef __uint64_t u_int64_t;
typedef __uint8_t __sa_family_t;
+typedef __uint32_t __socklen_t;
typedef va_list __va_list;
typedef size_t __size_t;
typedef __uint32_t __gid_t;
typedef __uint32_t __uid_t;
typedef __int32_t __clock_t;
+typedef __int32_t __clockid_t; /* clock_gettime()... */
typedef int __ct_rune_t; /* arg type for ctype funcs */
typedef __ct_rune_t __rune_t; /* rune_t (see above) */
typedef __uint16_t __mode_t; /* permissions */
typedef __int64_t __off_t; /* file offset */
typedef __int32_t __pid_t; /* process [group] */
+typedef __int64_t __rlim_t; /* resource limit - intentionally */
+ /* signed, because of legacy code */
+ /* that uses -1 for RLIM_INFINITY */
#define _HAVE_SYSTYPES
typedef long __key_t; /* IPC key (for Sys V IPC) */
--- /dev/null
+/*
+ * Copyright (c) 2013, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _SYS_EPOLL_H_
+#define _SYS_EPOLL_H_
+
+#include <stdint.h>
+
+#define EPOLL_CLOEXEC 02000000
+#define EPOLL_NONBLOCK 04000
+
+#define EPOLLIN 0x00000001
+#define EPOLLPRI 0x00000002
+#define EPOLLOUT 0x00000004
+#define EPOLLERR 0x00000008
+#define EPOLLHUP 0x00000010
+#define EPOLLRDNORM 0x00000040
+#define EPOLLRDBAND 0x00000080
+#define EPOLLWRNORM 0x00000100
+#define EPOLLWRBAND 0x00000200
+#define EPOLLMSG 0x00000400
+#define EPOLLRDHUP 0x00002000
+#define EPOLLWAKEUP 0x20000000
+#define EPOLLONESHOT 0x40000000
+#define EPOLLET 0x80000000
+
+#define EPOLL_CTL_ADD 1
+#define EPOLL_CTL_DEL 2
+#define EPOLL_CTL_MOD 3
+
+typedef union epoll_data
+{
+ void *ptr;
+ int fd;
+ uint32_t u32;
+ uint64_t u64;
+} epoll_data_t;
+
+struct epoll_event
+{
+ uint32_t events; /* Epoll events */
+ epoll_data_t data; /* User data variable */
+} __attribute__ ((__packed__));
+
+int epoll_create(int size);
+int epoll_create1(int flags);
+int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
+int epoll_wait(int epfd, struct epoll_event *events,
+ int max, int timeout);
+int epoll_pwait(int epfd, struct epoll_event *events,
+ int max, int timeout, const sigset_t *sigmask);
+
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)mman.h 8.2 (Berkeley) 1/9/95
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_MMAN_H_
+#define _SYS_MMAN_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#if __BSD_VISIBLE
+/*
+ * Inheritance for minherit()
+ */
+#define INHERIT_SHARE 0
+#define INHERIT_COPY 1
+#define INHERIT_NONE 2
+#endif
+
+/*
+ * Protections are chosen from these bits, or-ed together
+ */
+#define PROT_NONE 0x00 /* no permissions */
+#define PROT_READ 0x01 /* pages can be read */
+#define PROT_WRITE 0x02 /* pages can be written */
+#define PROT_EXEC 0x04 /* pages can be executed */
+
+/*
+ * Flags contain sharing type and options.
+ * Sharing types; choose one.
+ */
+#define MAP_SHARED 0x0001 /* share changes */
+#define MAP_PRIVATE 0x0002 /* changes are private */
+#if __BSD_VISIBLE
+#define MAP_COPY MAP_PRIVATE /* Obsolete */
+#endif
+
+/*
+ * Other flags
+ */
+#define MAP_FIXED 0x0010 /* map addr must be exactly as requested */
+
+#if __BSD_VISIBLE
+#define MAP_RENAME 0x0020 /* Sun: rename private pages to file */
+#define MAP_NORESERVE 0x0040 /* Sun: don't reserve needed swap area */
+#define MAP_RESERVED0080 0x0080 /* previously misimplemented MAP_INHERIT */
+#define MAP_RESERVED0100 0x0100 /* previously unimplemented MAP_NOEXTEND */
+#define MAP_HASSEMAPHORE 0x0200 /* region may contain semaphores */
+#define MAP_STACK 0x0400 /* region grows down, like a stack */
+#define MAP_NOSYNC 0x0800 /* page to but do not sync underlying file */
+
+/*
+ * Mapping type
+ */
+#define MAP_FILE 0x0000 /* map from file (default) */
+#define MAP_ANON 0x1000 /* allocated from memory, swap space */
+#ifndef _KERNEL
+#define MAP_ANONYMOUS MAP_ANON /* For compatibility. */
+#endif /* !_KERNEL */
+
+/*
+ * Extended flags
+ */
+#define MAP_NOCORE 0x00020000 /* dont include these pages in a coredump */
+#define MAP_PREFAULT_READ 0x00040000 /* prefault mapping for reading */
+#endif /* __BSD_VISIBLE */
+
+#if __POSIX_VISIBLE >= 199309
+/*
+ * Process memory locking
+ */
+#define MCL_CURRENT 0x0001 /* Lock only current memory */
+#define MCL_FUTURE 0x0002 /* Lock all future memory as well */
+#endif
+
+/*
+ * Error return from mmap()
+ */
+#define MAP_FAILED ((void *)-1)
+
+/*
+ * msync() flags
+ */
+#define MS_SYNC 0x0000 /* msync synchronously */
+#define MS_ASYNC 0x0001 /* return immediately */
+#define MS_INVALIDATE 0x0002 /* invalidate all cached data */
+
+/*
+ * Advice to madvise
+ */
+#define _MADV_NORMAL 0 /* no further special treatment */
+#define _MADV_RANDOM 1 /* expect random page references */
+#define _MADV_SEQUENTIAL 2 /* expect sequential page references */
+#define _MADV_WILLNEED 3 /* will need these pages */
+#define _MADV_DONTNEED 4 /* dont need these pages */
+
+#if __BSD_VISIBLE
+#define MADV_NORMAL _MADV_NORMAL
+#define MADV_RANDOM _MADV_RANDOM
+#define MADV_SEQUENTIAL _MADV_SEQUENTIAL
+#define MADV_WILLNEED _MADV_WILLNEED
+#define MADV_DONTNEED _MADV_DONTNEED
+#define MADV_FREE 5 /* dont need these pages, and junk contents */
+#define MADV_NOSYNC 6 /* try to avoid flushes to physical media */
+#define MADV_AUTOSYNC 7 /* revert to default flushing strategy */
+#define MADV_NOCORE 8 /* do not include these pages in a core file */
+#define MADV_CORE 9 /* revert to including pages in a core file */
+#define MADV_PROTECT 10 /* protect process from pageout kill */
+
+/*
+ * Return bits from mincore
+ */
+#define MINCORE_INCORE 0x1 /* Page is incore */
+#define MINCORE_REFERENCED 0x2 /* Page has been referenced by us */
+#define MINCORE_MODIFIED 0x4 /* Page has been modified by us */
+#define MINCORE_REFERENCED_OTHER 0x8 /* Page has been referenced */
+#define MINCORE_MODIFIED_OTHER 0x10 /* Page has been modified */
+#define MINCORE_SUPER 0x20 /* Page is a "super" page */
+
+/*
+ * Anonymous object constant for shm_open().
+ */
+#define SHM_ANON ((char *)1)
+#endif /* __BSD_VISIBLE */
+
+/*
+ * XXX missing POSIX_TYPED_MEM_* macros and
+ * posix_typed_mem_info structure.
+ */
+#if __POSIX_VISIBLE >= 200112
+#define POSIX_MADV_NORMAL _MADV_NORMAL
+#define POSIX_MADV_RANDOM _MADV_RANDOM
+#define POSIX_MADV_SEQUENTIAL _MADV_SEQUENTIAL
+#define POSIX_MADV_WILLNEED _MADV_WILLNEED
+#define POSIX_MADV_DONTNEED _MADV_DONTNEED
+#endif
+
+#ifndef _MODE_T_DECLARED
+typedef __mode_t mode_t;
+#define _MODE_T_DECLARED
+#endif
+
+#ifndef _OFF_T_DECLARED
+typedef __off_t off_t;
+#define _OFF_T_DECLARED
+#endif
+
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#define _SIZE_T_DECLARED
+#endif
+
+#if defined(_KERNEL) || defined(_WANT_FILE)
+#include <vm/vm.h>
+
+struct file;
+
+struct shmfd {
+ size_t shm_size;
+ vm_object_t shm_object;
+ int shm_refs;
+ uid_t shm_uid;
+ gid_t shm_gid;
+ mode_t shm_mode;
+ int shm_kmappings;
+
+ /*
+ * Values maintained solely to make this a better-behaved file
+ * descriptor for fstat() to run on.
+ */
+ struct timespec shm_atime;
+ struct timespec shm_mtime;
+ struct timespec shm_ctime;
+ struct timespec shm_birthtime;
+
+ struct label *shm_label; /* MAC label */
+ const char *shm_path;
+};
+#endif
+
+#ifdef _KERNEL
+int shm_mmap(struct shmfd *shmfd, vm_size_t objsize, vm_ooffset_t foff,
+ vm_object_t *obj);
+int shm_map(struct file *fp, size_t size, off_t offset, void **memp);
+int shm_unmap(struct file *fp, void *mem, size_t size);
+void shm_path(struct shmfd *shmfd, char *path, size_t size);
+
+#else /* !_KERNEL */
+
+__BEGIN_DECLS
+/*
+ * XXX not yet implemented: posix_mem_offset(), posix_typed_mem_get_info(),
+ * posix_typed_mem_open().
+ */
+#if __BSD_VISIBLE
+int getpagesizes(size_t *, int);
+int madvise(void *, size_t, int);
+int mincore(const void *, size_t, char *);
+int minherit(void *, size_t, int);
+#endif
+int mlock(const void *, size_t);
+#ifndef _MMAP_DECLARED
+#define _MMAP_DECLARED
+void * mmap(void *, size_t, int, int, int, off_t);
+#endif
+int mprotect(const void *, size_t, int);
+int msync(void *, size_t, int);
+int munlock(const void *, size_t);
+int munmap(void *, size_t);
+#if __POSIX_VISIBLE >= 200112
+int posix_madvise(void *, size_t, int);
+#endif
+#if __POSIX_VISIBLE >= 199309
+int mlockall(int);
+int munlockall(void);
+int shm_open(const char *, int, mode_t);
+int shm_unlink(const char *);
+#endif
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif /* !_SYS_MMAN_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)resource.h 8.4 (Berkeley) 1/9/95
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_RESOURCE_H_
+#define _SYS_RESOURCE_H_
+
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/_types.h>
+
+/*
+ * Process priority specifications to get/setpriority.
+ */
+#define PRIO_MIN -20
+#define PRIO_MAX 20
+
+#define PRIO_PROCESS 0
+#define PRIO_PGRP 1
+#define PRIO_USER 2
+
+/*
+ * Resource utilization information.
+ *
+ * All fields are only modified by curthread and
+ * no locks are required to read.
+ */
+
+#define RUSAGE_SELF 0
+#define RUSAGE_CHILDREN -1
+#define RUSAGE_THREAD 1
+
+struct rusage {
+ struct timeval ru_utime; /* user time used */
+ struct timeval ru_stime; /* system time used */
+ long ru_maxrss; /* max resident set size */
+#define ru_first ru_ixrss
+ long ru_ixrss; /* integral shared memory size */
+ long ru_idrss; /* integral unshared data " */
+ long ru_isrss; /* integral unshared stack " */
+ long ru_minflt; /* page reclaims */
+ long ru_majflt; /* page faults */
+ long ru_nswap; /* swaps */
+ long ru_inblock; /* block input operations */
+ long ru_oublock; /* block output operations */
+ long ru_msgsnd; /* messages sent */
+ long ru_msgrcv; /* messages received */
+ long ru_nsignals; /* signals received */
+ long ru_nvcsw; /* voluntary context switches */
+ long ru_nivcsw; /* involuntary " */
+#define ru_last ru_nivcsw
+};
+
+/*
+ * Resource limits
+ */
+#define RLIMIT_CPU 0 /* maximum cpu time in seconds */
+#define RLIMIT_FSIZE 1 /* maximum file size */
+#define RLIMIT_DATA 2 /* data size */
+#define RLIMIT_STACK 3 /* stack size */
+#define RLIMIT_CORE 4 /* core file size */
+#define RLIMIT_RSS 5 /* resident set size */
+#define RLIMIT_MEMLOCK 6 /* locked-in-memory address space */
+#define RLIMIT_NPROC 7 /* number of processes */
+#define RLIMIT_NOFILE 8 /* number of open files */
+#define RLIMIT_SBSIZE 9 /* maximum size of all socket buffers */
+#define RLIMIT_VMEM 10 /* virtual process size (incl. mmap) */
+#define RLIMIT_AS RLIMIT_VMEM /* standard name for RLIMIT_VMEM */
+#define RLIMIT_NPTS 11 /* pseudo-terminals */
+#define RLIMIT_SWAP 12 /* swap used */
+
+#define RLIM_NLIMITS 13 /* number of resource limits */
+
+#define RLIM_INFINITY ((rlim_t)(((uint64_t)1 << 63) - 1))
+/* XXX Missing: RLIM_SAVED_MAX, RLIM_SAVED_CUR */
+
+
+/*
+ * Resource limit string identifiers
+ */
+
+#ifdef _RLIMIT_IDENT
+static const char *rlimit_ident[RLIM_NLIMITS] = {
+ "cpu",
+ "fsize",
+ "data",
+ "stack",
+ "core",
+ "rss",
+ "memlock",
+ "nproc",
+ "nofile",
+ "sbsize",
+ "vmem",
+ "npts",
+ "swap",
+};
+#endif
+
+#ifndef _RLIM_T_DECLARED
+typedef __rlim_t rlim_t;
+#define _RLIM_T_DECLARED
+#endif
+
+struct rlimit {
+ rlim_t rlim_cur; /* current (soft) limit */
+ rlim_t rlim_max; /* maximum value for rlim_cur */
+};
+
+#if __BSD_VISIBLE
+
+struct orlimit {
+ __int32_t rlim_cur; /* current (soft) limit */
+ __int32_t rlim_max; /* maximum value for rlim_cur */
+};
+
+struct loadavg {
+ __fixpt_t ldavg[3];
+ long fscale;
+};
+
+#define CP_USER 0
+#define CP_NICE 1
+#define CP_SYS 2
+#define CP_INTR 3
+#define CP_IDLE 4
+#define CPUSTATES 5
+
+#endif /* __BSD_VISIBLE */
+
+#ifdef _KERNEL
+
+extern struct loadavg averunnable;
+void read_cpu_time(long *cp_time); /* Writes array of CPUSTATES */
+
+#else
+
+__BEGIN_DECLS
+/* XXX 2nd arg to [gs]etpriority() should be an id_t */
+int getpriority(int, int);
+int getrlimit(int, struct rlimit *);
+int getrusage(int, struct rusage *);
+int setpriority(int, int, int);
+int setrlimit(int, const struct rlimit *);
+__END_DECLS
+
+#endif /* _KERNEL */
+#endif /* !_SYS_RESOURCE_H_ */
--- /dev/null
+#include <signal.h>
#include <sys/cdefs.h>
#include <lwip/sockets.h>
+#include <sys/_iovec.h>
+
+/*
+ * Message header for recvmsg and sendmsg calls.
+ * Used value-result for recvmsg, value only for sendmsg.
+ */
+struct msghdr {
+ void *msg_name; /* optional address */
+ socklen_t msg_namelen; /* size of address */
+ struct iovec *msg_iov; /* scatter/gather array */
+ int msg_iovlen; /* # elements in msg_iov */
+ void *msg_control; /* ancillary data, see below */
+ socklen_t msg_controllen; /* ancillary data buffer len */
+ int msg_flags; /* flags on received message */
+};
#if __BSD_VISIBLE
#define AF_LOCAL AF_UNIX /* local to host (pipes, portals) */
#endif
#define AF_UNIX 1 /* standardized name for AF_LOCAL */
+#define AF_INET6 28 /* IPv6 */
#if __BSD_VISIBLE
#define AF_MAX 38
#endif
+#if __BSD_VISIBLE
+/*
+ * Protocol families, same as address families for now.
+ */
+#define PF_UNSPEC AF_UNSPEC
+#define PF_LOCAL AF_LOCAL
+#define PF_UNIX PF_LOCAL /* backward compatibility */
+#define PF_INET AF_INET
+#define PF_IMPLINK AF_IMPLINK
+#define PF_PUP AF_PUP
+#define PF_CHAOS AF_CHAOS
+#define PF_NETBIOS AF_NETBIOS
+#define PF_ISO AF_ISO
+#define PF_OSI AF_ISO
+#define PF_ECMA AF_ECMA
+#define PF_DATAKIT AF_DATAKIT
+#define PF_CCITT AF_CCITT
+#define PF_SNA AF_SNA
+#define PF_DECnet AF_DECnet
+#define PF_DLI AF_DLI
+#define PF_LAT AF_LAT
+#define PF_HYLINK AF_HYLINK
+#define PF_APPLETALK AF_APPLETALK
+#define PF_ROUTE AF_ROUTE
+#define PF_LINK AF_LINK
+#define PF_XTP pseudo_AF_XTP /* really just proto family, no AF */
+#define PF_COIP AF_COIP
+#define PF_CNT AF_CNT
+#define PF_SIP AF_SIP
+#define PF_IPX AF_IPX
+#define PF_RTIP pseudo_AF_RTIP /* same format as AF_INET */
+#define PF_PIP pseudo_AF_PIP
+#define PF_ISDN AF_ISDN
+#define PF_KEY pseudo_AF_KEY
+#define PF_INET6 AF_INET6
+#define PF_NATM AF_NATM
+#define PF_ATM AF_ATM
+#define PF_NETGRAPH AF_NETGRAPH
+#define PF_SLOW AF_SLOW
+#define PF_SCLUSTER AF_SCLUSTER
+#define PF_ARP AF_ARP
+#define PF_BLUETOOTH AF_BLUETOOTH
+#define PF_IEEE80211 AF_IEEE80211
+#define PF_INET_SDP AF_INET_SDP
+#define PF_INET6_SDP AF_INET6_SDP
+
+#define PF_MAX AF_MAX
+#endif
+
#ifndef _SA_FAMILY_T_DECLARED
typedef __sa_family_t sa_family_t;
#define _SA_FAMILY_T_DECLARED
#endif
+#include <sys/_sockaddr_storage.h>
+
__BEGIN_DECLS
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
+ssize_t recvmsg(int, struct msghdr *, int);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
+ssize_t sendmsg(int, const struct msghdr *, int);
int socket(int domain, int type, int protocol);
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int listen(int sockfd, int backlog);
/*
- * Copyright (c) 2007, 2008, 2009, 2011, 2012, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2011, 2012, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
mode_t umask(mode_t mask);
int chmod(const char *path, mode_t mode);
int mkdir(const char *pathname, int mode);
+int mkfifo(const char *pathname, mode_t mode);
int stat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat*buf);
int lstat(const char *path, struct stat *buf);
--- /dev/null
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)syslog.h 8.1 (Berkeley) 6/2/93
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_SYSLOG_H_
+#define _SYS_SYSLOG_H_
+
+#define _PATH_LOG "/var/run/log"
+#define _PATH_LOG_PRIV "/var/run/logpriv"
+#define _PATH_OLDLOG "/dev/log" /* backward compatibility */
+
+/*
+ * priorities/facilities are encoded into a single 32-bit quantity, where the
+ * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
+ * (0-big number). Both the priorities and the facilities map roughly
+ * one-to-one to strings in the syslogd(8) source code. This mapping is
+ * included in this file.
+ *
+ * priorities (these are ordered)
+ */
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but significant condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+
+#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */
+ /* extract priority */
+#define LOG_PRI(p) ((p) & LOG_PRIMASK)
+#define LOG_MAKEPRI(fac, pri) ((fac) | (pri))
+
+#ifdef SYSLOG_NAMES
+#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
+ /* mark "facility" */
+#define INTERNAL_MARK LOG_MAKEPRI((LOG_NFACILITIES<<3), 0)
+typedef struct _code {
+ const char *c_name;
+ int c_val;
+} CODE;
+
+CODE prioritynames[] = {
+ { "alert", LOG_ALERT, },
+ { "crit", LOG_CRIT, },
+ { "debug", LOG_DEBUG, },
+ { "emerg", LOG_EMERG, },
+ { "err", LOG_ERR, },
+ { "error", LOG_ERR, }, /* DEPRECATED */
+ { "info", LOG_INFO, },
+ { "none", INTERNAL_NOPRI, }, /* INTERNAL */
+ { "notice", LOG_NOTICE, },
+ { "panic", LOG_EMERG, }, /* DEPRECATED */
+ { "warn", LOG_WARNING, }, /* DEPRECATED */
+ { "warning", LOG_WARNING, },
+ { NULL, -1, }
+};
+#endif
+
+/* facility codes */
+#define LOG_KERN (0<<3) /* kernel messages */
+#define LOG_USER (1<<3) /* random user-level messages */
+#define LOG_MAIL (2<<3) /* mail system */
+#define LOG_DAEMON (3<<3) /* system daemons */
+#define LOG_AUTH (4<<3) /* authorization messages */
+#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
+#define LOG_LPR (6<<3) /* line printer subsystem */
+#define LOG_NEWS (7<<3) /* network news subsystem */
+#define LOG_UUCP (8<<3) /* UUCP subsystem */
+#define LOG_CRON (9<<3) /* clock daemon */
+#define LOG_AUTHPRIV (10<<3) /* authorization messages (private) */
+ /* Facility #10 clashes in DEC UNIX, where */
+ /* it's defined as LOG_MEGASAFE for AdvFS */
+ /* event logging. */
+#define LOG_FTP (11<<3) /* ftp daemon */
+#define LOG_NTP (12<<3) /* NTP subsystem */
+#define LOG_SECURITY (13<<3) /* security subsystems (firewalling, etc.) */
+#define LOG_CONSOLE (14<<3) /* /dev/console output */
+
+ /* other codes through 15 reserved for system use */
+#define LOG_LOCAL0 (16<<3) /* reserved for local use */
+#define LOG_LOCAL1 (17<<3) /* reserved for local use */
+#define LOG_LOCAL2 (18<<3) /* reserved for local use */
+#define LOG_LOCAL3 (19<<3) /* reserved for local use */
+#define LOG_LOCAL4 (20<<3) /* reserved for local use */
+#define LOG_LOCAL5 (21<<3) /* reserved for local use */
+#define LOG_LOCAL6 (22<<3) /* reserved for local use */
+#define LOG_LOCAL7 (23<<3) /* reserved for local use */
+
+#define LOG_NFACILITIES 24 /* current number of facilities */
+#define LOG_FACMASK 0x03f8 /* mask to extract facility part */
+ /* facility of pri */
+#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
+
+#ifdef SYSLOG_NAMES
+CODE facilitynames[] = {
+ { "auth", LOG_AUTH, },
+ { "authpriv", LOG_AUTHPRIV, },
+ { "console", LOG_CONSOLE, },
+ { "cron", LOG_CRON, },
+ { "daemon", LOG_DAEMON, },
+ { "ftp", LOG_FTP, },
+ { "kern", LOG_KERN, },
+ { "lpr", LOG_LPR, },
+ { "mail", LOG_MAIL, },
+ { "mark", INTERNAL_MARK, }, /* INTERNAL */
+ { "news", LOG_NEWS, },
+ { "ntp", LOG_NTP, },
+ { "security", LOG_SECURITY, },
+ { "syslog", LOG_SYSLOG, },
+ { "user", LOG_USER, },
+ { "uucp", LOG_UUCP, },
+ { "local0", LOG_LOCAL0, },
+ { "local1", LOG_LOCAL1, },
+ { "local2", LOG_LOCAL2, },
+ { "local3", LOG_LOCAL3, },
+ { "local4", LOG_LOCAL4, },
+ { "local5", LOG_LOCAL5, },
+ { "local6", LOG_LOCAL6, },
+ { "local7", LOG_LOCAL7, },
+ { NULL, -1, }
+};
+#endif
+
+#ifdef _KERNEL
+#define LOG_PRINTF -1 /* pseudo-priority to indicate use of printf */
+#endif
+
+/*
+ * arguments to setlogmask.
+ */
+#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */
+#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */
+
+/*
+ * Option flags for openlog.
+ *
+ * LOG_ODELAY no longer does anything.
+ * LOG_NDELAY is the inverse of what it used to be.
+ */
+#define LOG_PID 0x01 /* log the pid with each message */
+#define LOG_CONS 0x02 /* log on the console if errors in sending */
+#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */
+#define LOG_NDELAY 0x08 /* don't delay open */
+#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */
+#define LOG_PERROR 0x20 /* log to stderr as well */
+
+#ifdef _KERNEL
+
+#else /* not _KERNEL */
+
+/*
+ * Don't use va_list in the vsyslog() prototype. Va_list is typedef'd in two
+ * places (<machine/varargs.h> and <machine/stdarg.h>), so if we include one
+ * of them here we may collide with the utility's includes. It's unreasonable
+ * for utilities to have to include one of them to include syslog.h, so we get
+ * __va_list from <sys/_types.h> and use it.
+ */
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+__BEGIN_DECLS
+void closelog(void);
+void openlog(const char *, int, int);
+int setlogmask(int);
+void syslog(int, const char *, ...) __printflike(2, 3);
+#if __BSD_VISIBLE
+void vsyslog(int, const char *, __va_list) __printflike(2, 0);
+#endif
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif
#endif
#endif
+typedef char * caddr_t; /* core address */
+typedef const char * c_caddr_t; /* core address, pointer to const */
+
//typedef int fd_set;
typedef long ino_t;
typedef long dev_t;
#define _CLOCK_T_DECLARED
#endif
+#ifndef _CLOCKID_T_DECLARED
+typedef __clockid_t clockid_t;
+#define _CLOCKID_T_DECLARED
+#endif
+
#ifndef _TIME_T_DECLARED
typedef __time_t time_t;
#define _TIME_T_DECLARED
#endif
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* and nanoseconds */
+};
+
#ifndef _UID_T_DECLARED
typedef __uid_t uid_t;
#define _UID_T_DECLARED
#define _GID_T_DECLARED
#endif
+#ifndef _SA_FAMILY_T_DECLARED
+typedef __sa_family_t sa_family_t;
+#define _SA_FAMILY_T_DECLARED
+#endif
+
typedef unsigned long useconds_t;
typedef long suseconds_t;
--- /dev/null
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sysexits.h 8.1 (Berkeley) 6/2/93
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYSEXITS_H_
+#define _SYSEXITS_H_
+
+/*
+ * SYSEXITS.H -- Exit status codes for system programs.
+ *
+ * This include file attempts to categorize possible error
+ * exit statuses for system programs, notably delivermail
+ * and the Berkeley network.
+ *
+ * Error numbers begin at EX__BASE to reduce the possibility of
+ * clashing with other exit statuses that random programs may
+ * already return. The meaning of the codes is approximately
+ * as follows:
+ *
+ * EX_USAGE -- The command was used incorrectly, e.g., with
+ * the wrong number of arguments, a bad flag, a bad
+ * syntax in a parameter, or whatever.
+ * EX_DATAERR -- The input data was incorrect in some way.
+ * This should only be used for user's data & not
+ * system files.
+ * EX_NOINPUT -- An input file (not a system file) did not
+ * exist or was not readable. This could also include
+ * errors like "No message" to a mailer (if it cared
+ * to catch it).
+ * EX_NOUSER -- The user specified did not exist. This might
+ * be used for mail addresses or remote logins.
+ * EX_NOHOST -- The host specified did not exist. This is used
+ * in mail addresses or network requests.
+ * EX_UNAVAILABLE -- A service is unavailable. This can occur
+ * if a support program or file does not exist. This
+ * can also be used as a catchall message when something
+ * you wanted to do doesn't work, but you don't know
+ * why.
+ * EX_SOFTWARE -- An internal software error has been detected.
+ * This should be limited to non-operating system related
+ * errors as possible.
+ * EX_OSERR -- An operating system error has been detected.
+ * This is intended to be used for such things as "cannot
+ * fork", "cannot create pipe", or the like. It includes
+ * things like getuid returning a user that does not
+ * exist in the passwd file.
+ * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
+ * etc.) does not exist, cannot be opened, or has some
+ * sort of error (e.g., syntax error).
+ * EX_CANTCREAT -- A (user specified) output file cannot be
+ * created.
+ * EX_IOERR -- An error occurred while doing I/O on some file.
+ * EX_TEMPFAIL -- temporary failure, indicating something that
+ * is not really an error. In sendmail, this means
+ * that a mailer (e.g.) could not create a connection,
+ * and the request should be reattempted later.
+ * EX_PROTOCOL -- the remote system returned something that
+ * was "not possible" during a protocol exchange.
+ * EX_NOPERM -- You did not have sufficient permission to
+ * perform the operation. This is not intended for
+ * file system problems, which should use NOINPUT or
+ * CANTCREAT, but rather for higher level permissions.
+ */
+
+#define EX_OK 0 /* successful termination */
+
+#define EX__BASE 64 /* base value for error messages */
+
+#define EX_USAGE 64 /* command line usage error */
+#define EX_DATAERR 65 /* data format error */
+#define EX_NOINPUT 66 /* cannot open input */
+#define EX_NOUSER 67 /* addressee unknown */
+#define EX_NOHOST 68 /* host name unknown */
+#define EX_UNAVAILABLE 69 /* service unavailable */
+#define EX_SOFTWARE 70 /* internal software error */
+#define EX_OSERR 71 /* system error (e.g., can't fork) */
+#define EX_OSFILE 72 /* critical OS file missing */
+#define EX_CANTCREAT 73 /* can't create (user) output file */
+#define EX_IOERR 74 /* input/output error */
+#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
+#define EX_PROTOCOL 76 /* remote error in protocol */
+#define EX_NOPERM 77 /* permission denied */
+#define EX_CONFIG 78 /* configuration error */
+
+#define EX__MAX 78 /* maximum listed value */
+
+#endif /* !_SYSEXITS_H_ */
--- /dev/null
+#include <sys/syslog.h>
#include <pwd.h>
#include <fcntl.h> // for pid_t
#include <sys/socket.h>
+#include <sys/select.h>
+#include <getopt.h>
#define R_OK 4
#define W_OK 2
char *ttyname(int fd);
int unlink(const char*pathname);
int write(int fd, const void *buf, size_t len);
+int usleep(useconds_t usec);
+unsigned int sleep(unsigned int seconds);
__END_DECLS
#endif // __BF_UNISTD_H
/*
- * Copyright (c) 2007, 2008, 2009, 2011, 2012, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2011, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
__BEGIN_DECLS
#define MIN_FD 0
-#define MAX_FD 132
+//#define MAX_FD 132
+#define MAX_FD 4096
enum fdtab_type {
FDTAB_TYPE_AVAILABLE,
FDTAB_TYPE_STDOUT,
FDTAB_TYPE_STDERR,
FDTAB_TYPE_LWIP_SOCKET,
+ FDTAB_TYPE_EPOLL_INSTANCE,
FDTAB_TYPE_PTM, ///< master side of pseudo-terminal
FDTAB_TYPE_PTS, ///< slave side of pseudo-terminal
};
+#include <signal.h>
+#include <sys/epoll.h>
+
+struct _epoll_events_list {
+ struct _epoll_events_list *prev, *next;
+ struct epoll_event event;
+ int fd;
+};
+
struct fdtab_entry {
enum fdtab_type type;
// union {
int fd;
int inherited;
// };
+ int epoll_fd;
+ struct _epoll_events_list epoll_events;
};
int fdtab_alloc(struct fdtab_entry *h);
*/
/*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
#include <arch/x86/perfmon.h>
#include <arch/x86/apic.h>
-static bool perfmon_amd = false;
-static bool perfmon_intel = false;
+static bool perfmon_amd = false, perfmon_intel = false;
/* static bool perfmon_measurement_running = false; */
/* static bool perfmon_apic_activated = false; */
static uint64_t perfmon_cntr_init = 0;
-struct capability perfmon_callback_ep;
-
+struct capability perfmon_callback_ep = {
+ .type = ObjType_Null,
+};
void perfmon_init(void)
{
}
}
- // Activate performance measurement for Intel
if(perfmon_amd) {
-
perfmon_amd_measure_write(ctr*-1, 0);
perfmon_amd_measure_start(event, umask, kernel, counter_id, ctr!=0);
- perfmon_cntr_init = ctr;
}
+
+ // Activate performance measurement for Intel
+ if(perfmon_intel) {
+ perfmon_intel_measure_write(ctr*-1);
+ perfmon_intel_measure_start(event, umask, kernel, counter_id, ctr!=0);
+ }
+
+ perfmon_cntr_init = ctr;
}
/*
if(perfmon_amd) {
perfmon_amd_measure_write(perfmon_cntr_init*-1, 0);
}
+ if(perfmon_intel) {
+ perfmon_intel_reset();
+ perfmon_intel_measure_write(perfmon_cntr_init*-1);
+ }
}
-
uint64_t perfmon_measure_read(void)
{
{
if(perfmon_amd) {
perfmon_amd_measure_stop(0);
- } else if(perfmon_intel) {
- panic("Intel performance monitoring not supported yet.");
}
// Mask out performance counter overflow interrupts on APIC
*/
/*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
cpuid_apm_gen_t apmgen = cpuid_apm_gen_rd(&mycpuid);
- printf("Architectural Performance Monitoring version %d, # counters %d, "
- "# events %d\n", apmgen.version, apmgen.num_counters,
+ printf("Architectural Performance Monitoring version %d, # counters %d "
+ "(%d bits wide), # events %d\n",
+ apmgen.version, apmgen.num_counters, apmgen.width,
apmgen.vec_length);
- if(apmgen.version == 2) {
+ if(apmgen.version >= 2) {
cpuid_apm_fixed_t apmfixed = cpuid_apm_fixed_rd(&mycpuid);
-
- printf("# fixed function counters %d\n", apmfixed.num);
+ printf("# fixed function counters %d (%d bits wide)\n",
+ apmfixed.num, apmfixed.width);
}
char str[256];
cpuid_apm_feat_pr(str, 256, &mycpuid);
printf("Supported events:\n%s\n", str);
+ uint32_t apmfeat = cpuid_apm_feat_rd_raw(&mycpuid);
+ printf("Supported events: %x\n", apmfeat);
+
+ uint32_t status = ia32_perf_global_ctrl_rd(&ia32);
+ printf("Enabling counter %d, old val %x\n", 0, status);
+ ia32_perf_global_ctrl_pmc0_wrf(&ia32, 1);
+
return SYS_ERR_OK;
}
-void perfmon_intel_measure_start(uint8_t event, uint8_t umask)
+void perfmon_intel_reset(void)
+{
+ uint32_t status = ia32_perf_global_status_rd(&ia32);
+ ia32_perf_global_over_wr(&ia32, status);
+}
+
+void perfmon_intel_measure_start(uint8_t event, uint8_t umask, bool os,
+ uint8_t idx, bool intr)
{
ia32_perfevtsel_t sel0 = ia32_perfevtsel_default;
sel0 = ia32_perfevtsel_evsel_insert(sel0, event);
sel0 = ia32_perfevtsel_umask_insert(sel0, umask);
- sel0 = ia32_perfevtsel_usr_insert (sel0, 1);
- sel0 = ia32_perfevtsel_os_insert (sel0, 0);
+ sel0 = ia32_perfevtsel_usr_insert(sel0, 1);
+ sel0 = ia32_perfevtsel_os_insert(sel0, os ? 1 : 0);
+ sel0 = ia32_perfevtsel_intr_insert(sel0, intr ? 1 : 0);
sel0 = ia32_perfevtsel_en_insert (sel0, 1);
ia32_perfevtsel0_wr(&ia32, sel0);
}
if (err_no(err) == SYS_ERR_LMP_BUF_OVERFLOW) {
struct dispatcher_shared_generic *disp =
get_dispatcher_shared_generic(cap->u.endpoint.listener->disp);
- printk(LOG_DEBUG, "%.*s: IRQ message buffer overflow\n",
- DISP_NAME_LEN, disp->name);
+ printk(LOG_DEBUG, "%.*s: IRQ message buffer overflow on IRQ %d\n",
+ DISP_NAME_LEN, disp->name, irq);
} else {
printk(LOG_ERR, "Unexpected error delivering IRQ\n");
}
// APIC timer interrupt: handle in kernel and reschedule
if (vector == APIC_TIMER_INTERRUPT_VECTOR) {
apic_eoi();
- assert(kernel_ticks_enabled);
- update_kernel_now();
- trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_TIMER, kernel_now);
- wakeup_check(kernel_now);
+ assert(kernel_ticks_enabled);
+ update_kernel_now();
+ trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_TIMER, kernel_now);
+ wakeup_check(kernel_now);
} else if (vector == APIC_PERFORMANCE_INTERRUPT_VECTOR) {
// Handle performance counter overflow
// Reset counters
};
strncpy(data.name, disp->name, PERFMON_DISP_NAME_LEN);
- // Call overflow handler represented by endpoint
+ // Call overflow handler represented by endpoint
extern struct capability perfmon_callback_ep;
- errval_t err;
- size_t payload_len = sizeof(struct perfmon_overflow_data)/
- sizeof(uintptr_t)+1;
- err = lmp_deliver_payload(&perfmon_callback_ep,
- NULL,
- (uintptr_t*) &data,
- payload_len,
- false);
-
- // Make sure delivery was okay. SYS_ERR_LMP_BUF_OVERFLOW is okay for now
- assert(err_is_ok(err) || err_no(err)==SYS_ERR_LMP_BUF_OVERFLOW);
+ errval_t err;
+ size_t payload_len = sizeof(struct perfmon_overflow_data)/
+ sizeof(uintptr_t)+1;
+ err = lmp_deliver_payload(&perfmon_callback_ep,
+ NULL,
+ (uintptr_t*) &data,
+ payload_len,
+ false);
+
+ // Make sure delivery was okay. SYS_ERR_LMP_BUF_OVERFLOW is okay for now
+ assert(err_is_ok(err) || err_no(err)==SYS_ERR_LMP_BUF_OVERFLOW);
} else {
// This should never happen, as interrupts are disabled in kernel
printf("Performance counter overflow interrupt from "
* \param cpu_save_area Pointer to save area for registers stacked by CPU
* \param disp_save_area Pointer to save area in dispatcher
*/
-static __attribute__ ((used)) void
+static __attribute__ ((used, noreturn)) void
generic_handle_irq(int vector,
uintptr_t * NONNULL COUNT(X86_SAVE_AREA_SIZE) cpu_save_area,
struct registers_x86_64 *disp_save_area)
}
handle_irq(vector);
+ resume(disp_save_area);
}
/* Utility function for code below; initialises a gate_descriptor */
debug(SUBSYS_STARTUP, "RAM %lx--%lx\n", base_addr, end_addr);
err = create_caps_to_cnode(base_addr, end_addr - base_addr,
RegionType_Empty, &spawn_state, bootinfo);
- assert(err_is_ok(err));
+ if(err_is_fail(err)) {
+ printk(LOG_WARN, "Skipping RAM %lx--%lx...\n", base_addr, end_addr);
+ }
+ /* assert(err_is_ok(err)); */
}
} else if (mmap->base_addr > local_phys_to_gen_phys(init_alloc_addr)) {
/* XXX: The multiboot spec just says that mapping types other than
#include <arch/x86/timing.h>
#include <fpu.h>
#include <arch/x86/ipi_notify.h>
+#include <amd_vmcb_dev.h>
#define MIN(a,b) ((a) < (b) ? (a) : (b))
save_area = &disp->enabled_save_area;
}
+ // Should be enabled. Else, how do we do an invocation??
+ if(dcb_current->disabled) {
+ panic("Dispatcher needs to be enabled for this invocation");
+ }
+
// save calling dispatcher's registers, so that when the dispatcher
// next runs, it has a valid state in the relevant save area.
// Save RIP, RFLAGS, RSP and set RAX (return value) for later resume
save_area->eflags = rflags;
save_area->rsp = user_stack_save;
- /* save and zero FS/GS selectors (they're unmodified by the syscall path) */
- __asm ("mov %%fs, %[fs] \n\t"
- "mov %%gs, %[gs] \n\t"
- "mov %[zero], %%fs \n\t"
- "mov %[zero], %%gs \n\t"
- : /* No output */
- :
- [fs] "m" (save_area->fs),
- [gs] "m" (save_area->gs),
- [zero] "r" (0)
- );
+ if(!dcb_current->is_vm_guest) {
+ /* save and zero FS/GS selectors (they're unmodified by the syscall path) */
+ __asm ("mov %%fs, %[fs] \n\t"
+ "mov %%gs, %[gs] \n\t"
+ "mov %[zero], %%fs \n\t"
+ "mov %[zero], %%gs \n\t"
+ : /* No output */
+ :
+ [fs] "m" (save_area->fs),
+ [gs] "m" (save_area->gs),
+ [zero] "r" (0)
+ );
+ } else {
+ lpaddr_t lpaddr = gen_phys_to_local_phys(dcb_current->guest_desc.vmcb.cap.u.frame.base);
+ amd_vmcb_t vmcb;
+ amd_vmcb_initialize(&vmcb, (void *)local_phys_to_mem(lpaddr));
+ save_area->fs = amd_vmcb_fs_selector_rd(&vmcb);
+ save_area->gs = amd_vmcb_gs_selector_rd(&vmcb);
+ }
dispatch(to->u.endpoint.listener);
panic("dispatch returned");
retval.value = timing_get_apic_ticks_per_sec();
break;
+ case DEBUG_GET_APIC_ID:
+ retval.value = apic_get_id();
+ break;
+
default:
printk(LOG_ERR, "invalid sys_debug msg type\n");
}
#include <dispatch.h>
#include <exec.h>
#include <barrelfish_kpi/vmkit.h>
+#include <barrelfish_kpi/syscalls.h>
#include <amd_vmcb_dev.h>
}
void __attribute__ ((noreturn))
+vmkit_vmexec (struct dcb *dcb, lvaddr_t entry)
+{
+ dispatcher_handle_t handle = dcb->disp;
+ struct dispatcher_shared_generic *disp = get_dispatcher_shared_generic(handle);
+ lpaddr_t lpaddr = gen_phys_to_local_phys(dcb->guest_desc.ctrl.cap.u.frame.base);
+ struct guest_control *ctrl = (void *)local_phys_to_mem(lpaddr);
+ lpaddr = gen_phys_to_local_phys(dcb->guest_desc.vmcb.cap.u.frame.base);
+ amd_vmcb_t vmcb;
+ amd_vmcb_initialize(&vmcb, (void *)local_phys_to_mem(lpaddr));
+
+ memset(&ctrl->regs, 0, sizeof(struct registers_x86_64));
+ ctrl->regs.rdi = disp->udisp;
+ amd_vmcb_rip_wr(&vmcb, disp->dispatcher_run);
+ amd_vmcb_rsp_wr(&vmcb, 0);
+ amd_vmcb_rax_wr(&vmcb, 0);
+ amd_vmcb_rflags_wr_raw(&vmcb, USER_RFLAGS);
+ amd_vmcb_fs_selector_wr(&vmcb, 0);
+ amd_vmcb_gs_selector_wr(&vmcb, 0);
+ vmkit_vmenter(dcb);
+}
+
+struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
+ uint64_t *args, uint64_t rflags, uint64_t rip);
+
+extern uint64_t user_stack_save;
+
+void __attribute__ ((noreturn))
vmkit_vmenter (struct dcb *dcb)
{
lpaddr_t lpaddr = gen_phys_to_local_phys(dcb->guest_desc.ctrl.cap.u.frame.base);
amd_vmcb_cr3_wr(&vmcb, dcb->vspace);
}
+ vmenter_loop:
+
+ /* printf("vmenter IN\n"); */
+
// Enter the guest
vmkit_switch_to(dcb);
vm_exec(dcb);
vmkit_switch_from(dcb);
+ /* printf("vmenter OUT\n"); */
+
// Here we exited the guest due to some intercept triggered a vm exit
// our state is automatically restored by SVM
uint64_t ec = amd_vmcb_exitcode_rd(&vmcb);
/* We treat exits due to pysical interrupts (INTR, NMI, SMI) specially since
* they need to be processed by the kernel interrupt service routines */
- if (ec == VMEXIT_INTR || ec == VMEXIT_NMI || ec == VMEXIT_SMI) {
+ switch(ec) {
+ case VMEXIT_INTR:
+ case VMEXIT_NMI:
+ case VMEXIT_SMI:
+ {
+ arch_registers_state_t *area = NULL;
+
+ /* printf("INT at %" PRIx64 "\n", amd_vmcb_rip_rd(&vmcb)); */
ctrl->num_vm_exits_without_monitor_invocation++;
+
+ // Store user state into corresponding save area
+ if(dispatcher_is_disabled_ip(dcb->disp, amd_vmcb_rip_rd(&vmcb))) {
+ area = dispatcher_get_disabled_save_area(dcb->disp);
+ dcb->disabled = true;
+ } else {
+ area = dispatcher_get_enabled_save_area(dcb->disp);
+ dcb->disabled = false;
+ }
+ memcpy(area, &ctrl->regs, sizeof(arch_registers_state_t));
+ area->rax = amd_vmcb_rax_rd(&vmcb);
+ area->rip = amd_vmcb_rip_rd(&vmcb);
+ area->rsp = amd_vmcb_rsp_rd(&vmcb);
+ area->eflags = amd_vmcb_rflags_rd_raw(&vmcb);
+ area->fs = amd_vmcb_fs_selector_rd(&vmcb);
+ area->gs = amd_vmcb_gs_selector_rd(&vmcb);
+
// wait for interrupt will enable interrupts and therefore trigger their
// corresponding handlers (which may be the monitor)
wait_for_interrupt();
- } else {
+ }
+ break;
+
+ case VMEXIT_VMMCALL:
+ {
+ // Translate this to a SYSCALL
+ struct registers_x86_64 *regs = &ctrl->regs;
+ uint64_t args[10] = {
+ regs->r10, regs->r8, regs->r9, regs->r12, regs->r13, regs->r14,
+ regs->r15, amd_vmcb_rax_rd(&vmcb), regs->rbp, regs->rbx
+ };
+
+ /* printf("VMMCALL\n"); */
+
+ // Advance guest RIP to next instruction
+ amd_vmcb_rip_wr(&vmcb, amd_vmcb_rip_rd(&vmcb) + 3);
+ user_stack_save = amd_vmcb_rsp_rd(&vmcb);
+
+ struct sysret ret =
+ sys_syscall(regs->rdi, regs->rsi, regs->rdx, args,
+ amd_vmcb_rflags_rd_raw(&vmcb),
+ amd_vmcb_rip_rd(&vmcb));
+
+ amd_vmcb_rax_wr(&vmcb, ret.error);
+ regs->rdx = ret.value;
+ }
+ goto vmenter_loop;
+
+ default:
ctrl->num_vm_exits_with_monitor_invocation++;
/* the guest exited not due to an interrupt but some condition the
* monitor has to handle, therefore notify the monitor */
+ /* printf("OTHER\n"); */
+
assert(dcb->is_vm_guest);
// disable the domain
// call the monitor
errval_t err = lmp_deliver_notification(&dcb->guest_desc.monitor_ep.cap);
if (err_is_fail(err)) {
- printk(LOG_ERR, "Unexpected error delivering VMM call");
+ printk(LOG_ERR, "Unexpected error delivering VMEXIT");
}
// run the monitor
dispatch(dcb->guest_desc.monitor_ep.cap.u.endpoint.listener);
+ break;
}
}
*/
/*
- * Copyright (c) 2007, 2008, 2009, 2010, 2011, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
}
assert(dcb != NULL);
-#ifdef __x86_64__
- if (dcb->is_vm_guest) {
- vmkit_vmenter(dcb);
- panic("vmkit_vmenter unexpectedly returned");
- }
-#endif
dispatcher_handle_t handle = dcb->disp;
struct dispatcher_shared_generic *disp =
disp->name, (uint64_t)registers_get_ip(disabled_area));
assert(dispatcher_is_disabled_ip(handle,
registers_get_ip(disabled_area)));
- resume(disabled_area);
+ if(!dcb->is_vm_guest) {
+ resume(disabled_area);
+#ifdef __x86_64__
+ } else {
+ vmkit_vmenter(dcb);
+#endif
+ }
} else {
debug(SUBSYS_DISPATCH, "dispatch %.*s\n", DISP_NAME_LEN, disp->name);
assert(disp->dispatcher_run != 0);
disp->disabled = 1;
- execute(disp->dispatcher_run);
+ if(!dcb->is_vm_guest) {
+ execute(disp->dispatcher_run);
+#ifdef __x86_64__
+ } else {
+ vmkit_vmexec(dcb, disp->dispatcher_run);
+#endif
+ }
}
} // end function: dispatch
*/
/*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
errval_t perfmon_intel_init(void);
-void perfmon_intel_measure_start(uint8_t event, uint8_t umask);
+void perfmon_intel_measure_start(uint8_t event, uint8_t umask, bool os,
+ uint8_t idx, bool intr);
uint64_t perfmon_intel_measure_read(void);
void perfmon_intel_measure_write(uint64_t val);
+void perfmon_intel_reset(void);
#endif
*/
/*
- * Copyright (c) 2009, ETH Zurich.
+ * Copyright (c) 2009, 2013, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
errval_t vmkit_enable_virtualization (void);
int vmkit_disable_virtualization (void);
void __attribute__ ((noreturn)) vmkit_vmenter (struct dcb *dcb);
+void __attribute__ ((noreturn)) vmkit_vmexec (struct dcb *dcb, lvaddr_t entry);
#endif // _VMKIT_H
--- /dev/null
+--------------------------------------------------------------------------
+-- Copyright (c) 2007-2009, 2011, 2012, 2013, ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for lib/arranet
+--
+--------------------------------------------------------------------------
+
+[ build library { target = "arranet",
+ cFiles = [ "arranet.c", "inet_chksum.c", "ip_addr.c" ],
+ flounderDefs = [ "net_queue_manager" ]
+ }
+]
--- /dev/null
+/*
+ * Copyright (c) 2014, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich.
+ * Attn: Systems Group.
+ */
+
+/**
+ * \file
+ * \brief Arranet library code
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/inthandler.h>
+#include <sys/socket.h>
+#include <netif/e1000.h>
+#include <limits.h>
+#include <barrelfish/waitset.h>
+#include <barrelfish/waitset_chan.h>
+#include <lwip/sock_chan_support.h>
+#include <netdb.h>
+#include <arranet.h>
+#include <arranet_impl.h>
+
+#include "inet_chksum.h"
+
+#include <arranet_debug.h>
+
+static ether_terminate_queue ether_terminate_queue_ptr = NULL;
+static ether_get_mac_address_t ether_get_mac_address_ptr = NULL;
+static ether_transmit_pbuf_list_t ether_transmit_pbuf_list_ptr = NULL;
+static ether_get_tx_free_slots tx_free_slots_fn_ptr = NULL;
+static ether_handle_free_TX_slot handle_free_tx_slot_fn_ptr = NULL;
+static ether_rx_register_buffer rx_register_buffer_fn_ptr = NULL;
+static ether_rx_get_free_slots rx_get_free_slots_fn_ptr = NULL;
+
+uint64_t interrupt_counter = 0;
+uint64_t total_rx_p_count = 0;
+uint64_t total_rx_datasize = 0;
+struct client_closure *g_cl = NULL;
+
+//#define MAX_PACKETS 1024
+#define MAX_PACKETS 2000
+#define PACKET_SIZE 2048
+
+#define MAX_PEERS 256
+
+struct peer {
+ uint32_t ip;
+ struct eth_addr mac;
+};
+
+// Configure static ARP entries here
+// IP addresses are in network byte order!
+static struct peer peers[MAX_PEERS] = {
+ {
+ .ip = 0x0102000a, // 10.0.2.1
+ .mac.addr = "\x86\x86\x0b\xda\x22\xd7",
+ },
+ {
+ .ip = 0xaf06d080, // 128.208.6.175 - swingout2
+ .mac.addr = "\x90\xe2\xba\x3a\x2e\xdd",
+ },
+ {
+ .ip = 0xec06d080, // 128.208.6.236 - swingout3
+ .mac.addr = "\xa0\x36\x9f\x0f\xfb\xe2",
+ },
+ {
+ .ip = 0x8106d080, // 128.208.6.129 - swingout4
+ .mac.addr = "\xa0\x36\x9f\x10\x01\x6e",
+ },
+ {
+ .ip = 0x8206d080, // 128.208.6.130 - swingout5
+ .mac.addr = "\xa0\x36\x9f\x10\x00\xa2",
+ },
+ {
+ .ip = 0xc506d080, // 128.208.6.197 - swingout6
+ .mac.addr = "\xa0\x36\x9f\x10\x03\x52",
+ },
+};
+static int peers_alloc = 6; // Set number of static ARP here!
+
+#ifdef DEBUG_LATENCIES
+static int rx_packets_available = MAX_PACKETS;
+#endif
+
+struct socket {
+ struct socket *prev, *next;
+ int fd;
+ bool passive, nonblocking, connected, hangup, shutdown;
+ struct sockaddr_in bound_addr;
+ struct sockaddr_in peer_addr;
+ uint32_t my_seq, peer_seq, next_ack;
+};
+
+struct pkt_udp_headers {
+ struct eth_hdr eth;
+ struct ip_hdr ip;
+ struct udp_hdr udp;
+} __attribute__ ((packed));
+
+struct pkt_tcp_headers {
+ struct eth_hdr eth;
+ struct ip_hdr ip;
+ struct tcp_hdr tcp;
+} __attribute__ ((packed));
+
+// All known connections and those in progress
+static struct socket *connections = NULL;
+
+static struct socket sockets[MAX_FD];
+static struct packet rx_packets[MAX_PACKETS];
+
+// XXX: Needs to be per socket later on
+static struct waitset_chanstate recv_chanstate;
+static struct waitset_chanstate send_chanstate;
+
+static struct packet *inpkt = NULL;
+
+#ifdef DEBUG_LATENCIES
+static size_t memcache_packets_received = 0;
+static size_t output_pipeline_stalled = 0;
+static size_t port_cnt[65536];
+static int lwip_send_time[POSIX_TRANSA]; // Time until packet was delivered to network interface
+static size_t lwip_send_transactions = 0;
+int posix_recv_time[POSIX_TRANSA]; // Time until packet at exit of recvfrom
+size_t posix_recv_transactions = 0;
+static int posix_send_time[POSIX_TRANSA]; // Time until packet at entry to sendto
+static size_t posix_send_transactions = 0;
+
+int memcache_times[20][POSIX_TRANSA]; // Time until packet was delivered to network interface
+size_t memcache_transactions[20];
+
+size_t hash_option1 = 0;
+size_t hash_option2 = 0;
+size_t hash_option3 = 0;
+size_t hash_length = 0;
+size_t hash_calls = 0;
+size_t hash_aligned = 0;
+size_t hash_unaligned = 0;
+#endif
+
+static bool arranet_udp_accepted = false;
+static bool arranet_tcp_accepted = false;
+
+//#define TCP_LOCAL_PORT_RANGE_START 0xc000
+#define TCP_LOCAL_PORT_RANGE_START 8081
+#define TCP_LOCAL_PORT_RANGE_END 0xffff
+
+static uint16_t free_tcp_ports[TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1];
+static uint16_t free_tcp_tail = TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START,
+ free_tcp_free = TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1;
+
+#ifdef SENDMSG_WITH_COPY
+static uint16_t free_tcp_head = 0;
+
+// In network byte order
+static uint16_t tcp_new_port(void)
+{
+ if(free_tcp_free > 0) {
+ free_tcp_free--;
+ u16_t new_port = free_tcp_ports[free_tcp_head];
+ free_tcp_head = (free_tcp_head + 1) % (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1);
+ /* printf("Allocating port %d\n", new_port); */
+ return new_port;
+ } else {
+ printf("No more free ports!\n");
+ return 0;
+ }
+}
+#endif
+
+static void tcp_free_port(uint16_t port)
+{
+ /* if(pcb->local_port == 8080) { */
+ /* return; */
+ /* } */
+ /* if(pcb->local_port == 8080) { */
+ /* printf("Freeing 8080 from %p %p %p\n", */
+ /* __builtin_return_address(0), */
+ /* __builtin_return_address(1), */
+ /* __builtin_return_address(2)); */
+ /* } */
+ /* assert(pcb->local_port != 8080); */
+ assert(free_tcp_free < TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1);
+
+ /* printf("Freeing port %d\n", pcb->local_port); */
+
+ /* for(int i = 0; i < free_tcp_free; i++) { */
+ /* u16_t entry = free_tcp_ports[(i + free_tcp_head) % (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1)]; */
+ /* assert(entry != pcb->local_port); */
+ /* } */
+
+ free_tcp_free++;
+ free_tcp_tail = (free_tcp_tail + 1) % (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1);
+ free_tcp_ports[free_tcp_tail] = port;
+}
+
+static struct socket *free_sockets_queue[MAX_FD];
+static int free_sockets_head = 0, free_sockets_tail = MAX_FD - 1,
+ free_sockets = MAX_FD;
+
+static struct socket *alloc_socket(void)
+{
+ if(free_sockets == 0) {
+ return NULL;
+ }
+
+ free_sockets--;
+ struct socket *new_socket = free_sockets_queue[free_sockets_head];
+ // Reset all fields except FD
+ int fd_save = new_socket->fd;
+ uint32_t seq_save = new_socket->my_seq;
+ memset(new_socket, 0, sizeof(struct socket));
+ new_socket->fd = fd_save;
+ new_socket->my_seq = seq_save + 1000;
+ free_sockets_head = (free_sockets_head + 1) % MAX_FD;
+ /* printf("alloc_socket: returned %p\n", new_socket); */
+ return new_socket;
+}
+
+static void free_socket(struct socket *sock)
+{
+ /* printf("free_socket: %p\n", sock); */
+ assert(sock != NULL);
+ assert(free_sockets < MAX_FD);
+ free_sockets++;
+ free_sockets_tail = (free_sockets_tail + 1) % MAX_FD;
+ free_sockets_queue[free_sockets_tail] = sock;
+}
+
+/******** IP config *********/
+
+struct mac2ip {
+ uint8_t mac[ETHARP_HWADDR_LEN];
+ uint32_t ip;
+};
+
+static struct mac2ip ip_config[] = {
+ { // QEMU
+ .mac = "\x52\x54\x00\x12\x34\x56",
+ .ip = 0x0a00020f, // 10.0.2.15
+ },
+ {
+ // QEMU2
+ .mac = "\x52\x54\x00\x12\x34\x57",
+ .ip = 0xc0a80102, // 192.168.1.2
+ },
+ { // swingout1 (and swingout1-vf0)
+ .mac = "\xa0\x36\x9f\x10\x00\xa6",
+ .ip = 0x80d00643, // 128.208.6.67
+ },
+ { // swingout1-vf1
+ .mac = "\x22\xc9\xfc\x96\x83\xfc",
+ .ip = 0x80d00644, // 128.208.6.68
+ },
+ { // swingout1-vf2
+ .mac = "\xce\x43\x5b\xf7\x3e\x60",
+ .ip = 0x80d00602, // 128.208.6.2
+ },
+ { // swingout1-vf3
+ .mac = "\x6a\xb0\x62\xf6\xa7\x21",
+ .ip = 0x80d00603, // 128.208.6.3
+ },
+ { // swingout1-vf4
+ .mac = "\xb2\xdf\xf9\x39\xc6\x10",
+ .ip = 0x80d00604, // 128.208.6.4
+ },
+ { // swingout1-vf5
+ .mac = "\x92\x77\xe7\x3f\x80\x30",
+ .ip = 0x80d0060c, // 128.208.6.12
+ },
+ { // swingout5
+ .mac = "\xa0\x36\x9f\x10\x00\xa2",
+ .ip = 0x80d00682, // 128.208.6.130
+ },
+};
+
+static uint8_t arranet_mymac[ETHARP_HWADDR_LEN];
+static uint32_t arranet_myip = 0;
+
+/******** NYI *********/
+
+struct thread_mutex *lwip_mutex = NULL;
+struct waitset *lwip_waitset = NULL;
+
+void lwip_mutex_lock(void)
+{
+}
+
+void lwip_mutex_unlock(void)
+{
+}
+
+int lwip_read(int s, void *mem, size_t len)
+{
+ assert(!"NYI");
+}
+
+int lwip_write(int s, const void *data, size_t size)
+{
+ assert(!"NYI");
+}
+
+int lwip_fcntl(int s, int cmd, int val)
+{
+ struct socket *sock = &sockets[s];
+ int retval = 0;
+
+ switch(cmd) {
+ case F_GETFL:
+ retval = sock->nonblocking ? O_NONBLOCK : 0;
+ break;
+
+ case F_SETFL:
+ sock->nonblocking = val & O_NONBLOCK ? true : false;
+ break;
+
+ default:
+ assert(!"NYI");
+ retval = -1;
+ break;
+ }
+
+ return retval;
+}
+
+int lwip_listen(int s, int backlog)
+{
+ struct socket *sock = &sockets[s];
+ sock->passive = true;
+ return 0;
+}
+
+int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
+{
+ int retval = 0;
+
+ switch(level) {
+ case SOL_SOCKET:
+ switch(optname) {
+ case SO_SNDBUF:
+ {
+ assert(*optlen >= sizeof(int));
+ int *ret = optval;
+ *ret = PACKET_SIZE;
+ *optlen = sizeof(int);
+ }
+ break;
+
+ case SO_ERROR:
+ {
+ assert(*optlen >= sizeof(int));
+ int *ret = optval;
+ struct socket *sock = &sockets[s];
+ assert(sock != NULL);
+ *ret = sock->connected ? 0 : EINPROGRESS;
+ *optlen = sizeof(int);
+ }
+ break;
+
+ default:
+ assert(!"NYI");
+ retval = -1;
+ break;
+ }
+ break;
+
+ default:
+ assert(!"NYI");
+ retval = -1;
+ break;
+ }
+
+ return retval;
+}
+
+int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
+{
+ int retval = 0;
+
+ switch(level) {
+ case SOL_SOCKET:
+ switch(optname) {
+ case SO_REUSEADDR:
+ case SO_REUSEPORT:
+ // No-op
+ break;
+
+ case SO_SNDBUF:
+ {
+ int len = *(const int *)optval;
+ if(len > PACKET_SIZE) {
+ retval = -1;
+ }
+ }
+ break;
+
+ default:
+ printf("%d, %d\n", level, optname);
+ assert(!"NYI");
+ retval = -1;
+ break;
+ }
+ break;
+
+ case IPPROTO_TCP:
+ switch(optname) {
+ case TCP_NODELAY:
+ // XXX: No-op. We don't support Nagling anyway.
+ break;
+ }
+ break;
+
+ default:
+ assert(!"NYI");
+ retval = -1;
+ break;
+ }
+
+ return retval;
+}
+
+int lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
+{
+ struct socket *sock = &sockets[s];
+ assert(sock != NULL);
+ assert(*namelen >= sizeof(struct sockaddr_in));
+
+ memcpy(name, &sock->bound_addr, sizeof(struct sockaddr_in));
+ *namelen = sizeof(struct sockaddr_in);
+
+ return 0;
+}
+
+struct hostent *lwip_gethostbyname(const char *name)
+{
+ assert(!"NYI");
+}
+
+int lwip_getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct addrinfo *r = calloc(1, sizeof(struct addrinfo));
+ struct sockaddr_in *sa = calloc(1, sizeof(struct sockaddr_in));
+
+ assert(hints != NULL);
+
+ sa->sin_family = AF_INET;
+ sa->sin_port = htons(atoi(servname));
+ sa->sin_addr.s_addr = INADDR_ANY;
+
+ // Return dummy UDP socket address
+ r->ai_flags = AI_PASSIVE;
+ r->ai_family = AF_INET;
+ r->ai_socktype = SOCK_DGRAM;
+ r->ai_protocol = hints->ai_protocol;
+ r->ai_addrlen = sizeof(struct sockaddr_in);
+ r->ai_addr = (struct sockaddr *)sa;
+ r->ai_canonname = NULL;
+ r->ai_next = NULL;
+
+ *res = r;
+ return 0;
+}
+
+void lwip_freeaddrinfo(struct addrinfo *ai)
+{
+ for(struct addrinfo *i = ai; i != NULL;) {
+ struct addrinfo *oldi = i;
+ free(i->ai_addr);
+ i = i->ai_next;
+ free(oldi);
+ }
+}
+
+int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
+{
+ assert(!"NYI");
+}
+
+/* The following 2 are #defined in lwIP 1.4.1, but not in 1.3.1, duplicating them here */
+
+int inet_aton(const char *cp, struct in_addr *addr)
+{
+ return ipaddr_aton(cp, (ip_addr_t *)addr);
+}
+
+u32_t inet_addr(const char *cp)
+{
+ return ipaddr_addr(cp);
+}
+
+/***** lwIP-compatibility functions, so that NFS and RPC code compiles *****/
+
+u8_t pbuf_free_tagged(struct pbuf *p, const char *func_name, int line_no)
+{
+ assert(!"NYI");
+}
+
+u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
+{
+ assert(!"NYI");
+}
+
+struct udp_pcb;
+
+err_t udp_send(struct udp_pcb *pcb, struct pbuf *p);
+err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
+{
+ assert(!"NYI");
+}
+
+struct udp_pcb *udp_new(void);
+struct udp_pcb *udp_new(void)
+{
+ assert(!"NYI");
+}
+
+void udp_recv(struct udp_pcb *pcb,
+ void (*recvfn) (void *arg, struct udp_pcb * upcb,
+ struct pbuf * p,
+ struct ip_addr * addr,
+ u16_t port), void *recv_arg);
+void udp_recv(struct udp_pcb *pcb,
+ void (*recvfn) (void *arg, struct udp_pcb * upcb,
+ struct pbuf * p,
+ struct ip_addr * addr,
+ u16_t port), void *recv_arg)
+{
+ assert(!"NYI");
+}
+
+void udp_remove(struct udp_pcb *pcb);
+void udp_remove(struct udp_pcb *pcb)
+{
+ assert(!"NYI");
+}
+
+err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port);
+err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
+{
+ assert(!"NYI");
+}
+
+struct pbuf *pbuf_alloc_tagged(pbuf_layer layer, u16_t length, pbuf_type type, const char *func_name, int line_no)
+{
+ assert(!"NYI");
+}
+
+void lwip_record_event_simple(uint8_t event_type, uint64_t ts);
+void lwip_record_event_simple(uint8_t event_type, uint64_t ts)
+{
+ assert(!"NYI");
+}
+
+uint64_t wrapper_perform_lwip_work(void);
+uint64_t wrapper_perform_lwip_work(void)
+{
+ assert(!"NYI");
+}
+
+bool lwip_init_auto(void);
+bool lwip_init_auto(void)
+{
+ assert(!"NYI");
+}
+
+/******** NYI END *********/
+
+void ethernetif_backend_init(char *service_name, uint64_t queueid,
+ ether_get_mac_address_t get_mac_ptr,
+ ether_terminate_queue terminate_queue_ptr,
+ ether_transmit_pbuf_list_t transmit_ptr,
+ ether_get_tx_free_slots tx_free_slots_ptr,
+ ether_handle_free_TX_slot handle_free_tx_slot_ptr,
+ size_t rx_bufsz,
+ ether_rx_register_buffer rx_register_buffer_ptr,
+ ether_rx_get_free_slots rx_get_free_slots_ptr)
+{
+ ether_terminate_queue_ptr = terminate_queue_ptr;
+ ether_get_mac_address_ptr = get_mac_ptr;
+ ether_transmit_pbuf_list_ptr = transmit_ptr;
+ tx_free_slots_fn_ptr = tx_free_slots_ptr;
+ handle_free_tx_slot_fn_ptr = handle_free_tx_slot_ptr;
+ rx_register_buffer_fn_ptr = rx_register_buffer_ptr;
+ rx_get_free_slots_fn_ptr = rx_get_free_slots_ptr;
+ /* printf("PBUF_POOL_BUFSIZE = %u, rx buffer size = %zu\n", PBUF_POOL_BUFSIZE, */
+ /* rx_bufsz); */
+}
+
+#define MAX_DRIVER_BUFS 16
+
+static genpaddr_t rx_pbase = 0;
+static genvaddr_t rx_vbase = 0;
+
+static struct packet tx_packets[MAX_PACKETS];
+static uint8_t tx_bufs[MAX_PACKETS][PACKET_SIZE];
+static unsigned int tx_idx = 0;
+/* static ssize_t tx_packets_available = MAX_PACKETS; */
+
+static void packet_output(struct packet *p)
+{
+ struct driver_buffer bufs[MAX_DRIVER_BUFS];
+ int n = 0;
+
+#ifdef DEBUG_LATENCIES
+ if(memcache_transactions[6] < POSIX_TRANSA) {
+ if(p->next == NULL) {
+ assert(p->next == NULL && p->len >= sizeof(protocol_binary_request_no_extras));
+ protocol_binary_request_no_extras *mypayload = (void *)p->payload + SIZEOF_ETH_HDR + 20 + sizeof(struct udp_hdr) + UDP_HEADLEN;
+ memcache_times[6][memcache_transactions[6]] = get_time() - mypayload->message.header.request.opaque;
+ memcache_transactions[6]++;
+ } else {
+ protocol_binary_request_no_extras *mypayload = (void *)p->next->payload + UDP_HEADLEN;
+ memcache_times[6][memcache_transactions[6]] = get_time() - mypayload->message.header.request.opaque;
+ memcache_transactions[6]++;
+ }
+ }
+#endif
+
+ for (struct packet *q = p; q != NULL; q = q->next) {
+ struct driver_buffer *buf = &bufs[n];
+
+ /* if(q->payload < &tx_bufs[0][0] || q->payload >= &tx_bufs[MAX_PACKETS][PACKET_SIZE]) { */
+ /* printf("Called from %p %p\n", */
+ /* __builtin_return_address(0), */
+ /* __builtin_return_address(1)); */
+ /* assert(q->payload >= &tx_bufs[0][0] && q->payload < &tx_bufs[MAX_PACKETS][PACKET_SIZE]); */
+ /* } */
+
+ /* Send the data from the pbuf to the interface, one pbuf at a
+ time. The size of the data in each pbuf is kept in the ->len
+ variable. */
+ assert(q->len > 0);
+
+ // Check if it's from the RX region
+ if(((genvaddr_t)q->payload) >= rx_vbase &&
+ ((genvaddr_t)q->payload) < rx_vbase + (MAX_PACKETS * PACKET_SIZE + 4096)) {
+ buf->pa = rx_pbase + ((genvaddr_t)q->payload - rx_vbase);
+ } else {
+ // Check if it's in morecore's region
+ struct morecore_state *mc_state = get_morecore_state();
+ struct vspace_mmu_aware *mmu_state = &mc_state->mmu_state;
+ genvaddr_t base = vregion_get_base_addr(&mmu_state->vregion);
+ struct memobj_frame_list *i;
+
+ // Walk frame list
+ for(i = mmu_state->memobj.frame_list; i != NULL; i = i->next) {
+ // If address is completely within frame, we can resolve
+ // XXX: Everything else would be easier with an IOMMU
+ if(base + i->offset <= (genvaddr_t)q->payload &&
+ ((genvaddr_t)q->payload) + q->len < base + i->offset + i->size) {
+ assert(i->pa != 0);
+
+ /* buf->pa = id.base + ((genvaddr_t)q->payload - base - i->offset); */
+ buf->pa = i->pa + ((genvaddr_t)q->payload - base - i->offset);
+ break;
+ }
+ }
+
+ if(i == NULL) {
+ // Check if it's in text/data region
+ int entry;
+ for(entry = 0; entry < mc_state->v2p_entries; entry++) {
+ struct v2pmap *pmap = &mc_state->v2p_mappings[entry];
+
+ if(pmap->va <= (genvaddr_t)q->payload &&
+ ((genvaddr_t)q->payload) + q->len < pmap->va + pmap->size) {
+ buf->pa = pmap->pa + ((genvaddr_t)q->payload - pmap->va);
+ break;
+ }
+ }
+
+ if(entry == mc_state->v2p_entries) {
+ printf("Called from %p %p\n",
+ __builtin_return_address(0),
+ __builtin_return_address(1));
+
+ USER_PANIC("Invalid pbuf! payload = %p, pa = %p\n", q->payload, buf->pa);
+ }
+ }
+ }
+
+ /* printf("Sending: '%s'\n", (char *)q->payload); */
+
+ buf->va = q->payload;
+ buf->len = q->len;
+#ifndef SENDMSG_WITH_COPY
+ buf->opaque = q->opaque;
+#else
+ buf->opaque = q;
+#endif
+ buf->flags = q->flags;
+
+ n++;
+ }
+
+#ifdef DEBUG_LATENCIES
+ if(lwip_send_transactions < POSIX_TRANSA) {
+ struct ip_hdr *iphdr = (struct ip_hdr *)(p->payload + SIZEOF_ETH_HDR);
+
+ if(IPH_PROTO(iphdr) == IP_PROTO_UDP) {
+ struct udp_hdr *udphdr = (struct udp_hdr *)(p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+ if(htons(udphdr->src) == 11212 || htons(udphdr->src) == 11211) {
+ protocol_binary_response_no_extras *mypayload;
+ if(p->next != NULL) {
+ mypayload = (void *)p->next->next->payload;
+ } else {
+ mypayload = (void *)p->payload + sizeof(struct pkt_udp_headers) + UDP_HEADLEN;
+ }
+ lwip_send_time[lwip_send_transactions] = get_time() - mypayload->message.header.response.opaque;
+ lwip_send_transactions++;
+ } else if (htons(udphdr->src) == 1234) {
+ protocol_binary_request_no_extras *mypayload;
+ if(p->next == NULL) {
+ mypayload = (void *)p->payload + sizeof(struct pkt_udp_headers) + UDP_HEADLEN;
+ } else {
+ mypayload = (void *)p->next->payload + UDP_HEADLEN;
+ }
+ lwip_send_time[lwip_send_transactions] = get_time() - mypayload->message.header.request.opaque;
+ lwip_send_transactions++;
+ }
+ }
+ }
+#endif
+
+ errval_t err = ether_transmit_pbuf_list_ptr(bufs, n);
+ assert(err_is_ok(err));
+}
+
+void arranet_recv_free(struct packet *p)
+{
+ assert(p >= rx_packets && p < &rx_packets[MAX_PACKETS]);
+
+#ifdef DEBUG_LATENCIES
+ rx_packets_available++;
+#endif
+ errval_t err = rx_register_buffer_fn_ptr(p->pa, p->payload, p);
+ assert(err_is_ok(err));
+}
+
+struct recv_udp_args {
+ void *buf;
+ size_t len;
+ int recv_len;
+ struct sockaddr *src_addr;
+ socklen_t *addrlen;
+ struct packet **inpkt;
+};
+
+struct recv_tcp_args {
+ void *buf;
+ size_t len;
+ int recv_len;
+ struct sockaddr *src_addr;
+ socklen_t *addrlen;
+ struct packet **inpkt;
+ bool syn, for_me;
+ uint32_t in_seqno;
+ struct socket *sock;
+};
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+static void sock_recved_udp_packet(void *arg)
+{
+ struct recv_udp_args *args = arg;
+ assert(inpkt != NULL);
+ assert(inpkt->next == NULL);
+
+ // Process headers
+ struct ip_hdr *iphdr = (struct ip_hdr *)(inpkt->payload + SIZEOF_ETH_HDR);
+
+ assert(IPH_PROTO(iphdr) == IP_PROTO_UDP);
+
+ struct udp_hdr *udphdr = (struct udp_hdr *)(inpkt->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+ size_t hdr_len = SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr);
+ uint8_t *payload = inpkt->payload + hdr_len;
+ uint16_t pkt_len = htons(udphdr->len) - sizeof(struct udp_hdr);
+ assert(args->buf != NULL); // No accept() allowed
+
+ // Fill in src_addr if provided
+ if(args->src_addr != NULL) {
+ struct sockaddr_in *addr = (struct sockaddr_in *)args->src_addr;
+
+ assert(*args->addrlen >= sizeof(struct sockaddr_in));
+ memset(addr, 0, sizeof(struct sockaddr_in));
+ addr->sin_len = sizeof(struct sockaddr_in);
+ addr->sin_family = AF_INET;
+ addr->sin_port = udphdr->src;
+ addr->sin_addr.s_addr = iphdr->src.addr;
+ *args->addrlen = sizeof(struct sockaddr_in);
+ }
+
+ // It's a recvfrom!
+ if(args->len != 0) {
+#ifdef DEBUG_LATENCIES
+ if(memcache_transactions[0] < POSIX_TRANSA) {
+ protocol_binary_request_no_extras *mypayload = (void *)payload + UDP_HEADLEN;
+ memcache_times[0][memcache_transactions[0]] = get_time() - mypayload->message.header.request.opaque;
+ memcache_transactions[0]++;
+ }
+#endif
+
+ args->recv_len = MIN(args->len, pkt_len);
+ memcpy(args->buf, payload, args->recv_len);
+
+#ifdef DEBUG_LATENCIES
+ if(memcache_transactions[1] < POSIX_TRANSA) {
+ protocol_binary_request_no_extras *mypayload = (void *)payload + UDP_HEADLEN;
+ memcache_times[1][memcache_transactions[1]] = get_time() - mypayload->message.header.request.opaque;
+ memcache_transactions[1]++;
+ }
+#endif
+
+#ifdef DEBUG_LATENCIES
+ rx_packets_available++;
+#endif
+ errval_t err = rx_register_buffer_fn_ptr(inpkt->pa, inpkt->payload, inpkt);
+ assert(err_is_ok(err));
+ } else {
+ args->recv_len = pkt_len;
+ *((void **)args->buf) = payload;
+ *args->inpkt = inpkt;
+ }
+
+ // Input packet is consumed in stack
+ inpkt = NULL;
+}
+
+static void sock_recved_tcp_packet(void *arg)
+{
+ struct recv_tcp_args *args = arg;
+
+ // Received only a FIN?
+ if(inpkt == NULL) {
+ args->recv_len = 0;
+ args->for_me = true;
+ return;
+ }
+ assert(inpkt != NULL);
+ assert(inpkt->next == NULL);
+
+ // Process headers
+ struct ip_hdr *iphdr = (struct ip_hdr *)(inpkt->payload + SIZEOF_ETH_HDR);
+ assert(IPH_PROTO(iphdr) == IP_PROTO_TCP);
+ struct tcp_hdr *tcphdr = (struct tcp_hdr *)(inpkt->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+ size_t hdr_len = SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + (TCPH_HDRLEN(tcphdr) * 4);
+ uint8_t *payload = inpkt->payload + hdr_len;
+ uint16_t pkt_len = htons(IPH_LEN(iphdr)) - (TCPH_HDRLEN(tcphdr) * 4) - (IPH_HL(iphdr) * 4);
+
+ args->in_seqno = tcphdr->seqno;
+ args->for_me = true;
+
+ // Is this from an accept() call?
+ if(args->buf == NULL) {
+ if(TCPH_FLAGS(tcphdr) & TCP_SYN) {
+ args->syn = true;
+ } else {
+ // Don't consume packet
+ args->for_me = false;
+ return;
+ }
+ } else { // From a recv() call
+ if(TCPH_FLAGS(tcphdr) & TCP_SYN) {
+ // Don't consume packet
+ args->syn = true;
+ args->for_me = false;
+ return;
+ } else {
+ assert(args->sock != NULL);
+ // Is this for the socket that's calling?
+ if(tcphdr->dest != args->sock->bound_addr.sin_port ||
+ tcphdr->src != args->sock->peer_addr.sin_port) {
+ // Don't consume packet
+ args->for_me = false;
+ return;
+ }
+
+ if(args->len != 0) {
+ assert(args->len >= pkt_len);
+ args->recv_len = MIN(args->len, pkt_len);
+ memcpy(args->buf, payload, args->recv_len);
+ } else {
+ assert(!"NYI");
+ args->recv_len = pkt_len;
+ *((void **)args->buf) = payload;
+ *args->inpkt = inpkt;
+ }
+ }
+ }
+
+ // Fill in src_addr if provided
+ if(args->src_addr != NULL) {
+ struct sockaddr_in *addr = (struct sockaddr_in *)args->src_addr;
+
+ assert(*args->addrlen >= sizeof(struct sockaddr_in));
+ memset(addr, 0, sizeof(struct sockaddr_in));
+ addr->sin_len = sizeof(struct sockaddr_in);
+ addr->sin_family = AF_INET;
+ addr->sin_port = tcphdr->src;
+ addr->sin_addr.s_addr = iphdr->src.addr;
+ *args->addrlen = sizeof(struct sockaddr_in);
+ }
+
+#ifdef DEBUG_LATENCIES
+ rx_packets_available++;
+#endif
+ errval_t err = rx_register_buffer_fn_ptr(inpkt->pa, inpkt->payload, inpkt);
+ assert(err_is_ok(err));
+
+ // Input packet is consumed in stack
+ inpkt = NULL;
+}
+
+int lwip_recv(int s, void *mem, size_t len, int flags)
+{
+ /* printf("lwip_recv(%d)\n", s); */
+ assert(arranet_tcp_accepted);
+ struct socket *sock = &sockets[s];
+ struct recv_tcp_args args = {
+ .buf = mem,
+ .len = len,
+ .src_addr = NULL,
+ .syn = false,
+ .sock = sock,
+ };
+ struct waitset ws;
+ waitset_init(&ws);
+
+ errval_t err = waitset_chan_register_polled(&ws, &recv_chanstate,
+ MKCLOSURE(sock_recved_tcp_packet, &args));
+ assert(err_is_ok(err));
+
+ /* if socket is ready, trigger event right away */
+ if (lwip_sock_ready_read(s)) {
+ err = waitset_chan_trigger(&recv_chanstate);
+ assert(err_is_ok(err));
+ }
+
+ if(sock->nonblocking) {
+ err = event_dispatch_non_block(&ws);
+ if(err_no(err) == LIB_ERR_NO_EVENT || !args.for_me) {
+ err = waitset_chan_deregister(&recv_chanstate);
+ assert(err_is_ok(err) ||
+ (err_no(err) == LIB_ERR_CHAN_NOT_REGISTERED && !args.for_me));
+ errno = EAGAIN;
+ args.recv_len = -1;
+ } else {
+ errno = 0;
+ assert(err_is_ok(err));
+ }
+ } else {
+ err = event_dispatch(&ws);
+ assert(err_is_ok(err));
+ if(args.syn) {
+ assert(!"Will block forever");
+ }
+ errno = 0;
+ }
+
+ if(errno != EAGAIN) {
+ sock->peer_seq = htonl(args.in_seqno);
+ sock->next_ack = sock->peer_seq + args.recv_len;
+ /* printf("lwip_recv: Assigning %p, %x\n", sock, sock->next_ack); */
+ } else {
+ // Did it shutdown?
+ if(sock->hangup) {
+ errno = 0;
+ args.recv_len = 0;
+ }
+ }
+
+#ifdef DEBUG_LATENCIES
+ if(posix_recv_transactions < POSIX_TRANSA) {
+ protocol_binary_request_no_extras *mypayload = mem + UDP_HEADLEN;
+ posix_recv_time[posix_recv_transactions] = get_time() - mypayload->message.header.request.opaque;
+ posix_recv_transactions++;
+ }
+#endif
+
+ // Packet is now in buffer
+ /* printf("lwip_recv returned %d\n", args.recv_len); */
+ return args.recv_len;
+}
+
+int lwip_sendto(int s, const void *data, size_t size, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ struct iovec io = {
+ .iov_base = (void *)data,
+ .iov_len = size,
+ };
+
+ struct msghdr msg = {
+ .msg_name = (void *)to,
+ .msg_namelen = tolen,
+ .msg_iov = &io,
+ .msg_iovlen = 1,
+ .msg_flags = 0,
+ };
+
+ return lwip_sendmsg(s, &msg, flags);
+}
+
+int lwip_socket(int domain, int type, int protocol)
+{
+ // XXX: Accept UDP or TCP, based on created sockets
+ switch(type) {
+ case SOCK_STREAM:
+ assert(!arranet_udp_accepted);
+ arranet_tcp_accepted = true;
+ break;
+
+ case SOCK_DGRAM:
+ assert(!arranet_tcp_accepted);
+ arranet_udp_accepted = true;
+ break;
+ }
+
+ struct socket *sock = alloc_socket();
+ assert(sock != NULL);
+ /* printf("lwip_socket() = %d\n", sock->fd); */
+ return sock->fd;
+}
+
+int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ struct socket *sock = &sockets[s];
+ assert(name->sa_family == AF_INET);
+ assert(namelen >= sizeof(struct sockaddr_in));
+ sock->bound_addr = *(struct sockaddr_in *)name;
+ return 0;
+}
+
+int lwip_recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen)
+{
+ assert(arranet_udp_accepted);
+ struct socket *sock = &sockets[sockfd];
+ struct recv_udp_args args = {
+ .buf = buf,
+ .len = len,
+ .src_addr = src_addr,
+ .addrlen = addrlen,
+ };
+ struct waitset ws;
+ waitset_init(&ws);
+
+ errval_t err = waitset_chan_register_polled(&ws, &recv_chanstate,
+ MKCLOSURE(sock_recved_udp_packet, &args));
+ assert(err_is_ok(err));
+
+ /* if socket is ready, trigger event right away */
+ if (lwip_sock_ready_read(sockfd)) {
+ err = waitset_chan_trigger(&recv_chanstate);
+ assert(err_is_ok(err));
+ }
+
+ if(sock->nonblocking) {
+ err = event_dispatch_non_block(&ws);
+ if(err_no(err) == LIB_ERR_NO_EVENT) {
+ err = waitset_chan_deregister(&recv_chanstate);
+ assert(err_is_ok(err));
+ errno = EAGAIN;
+ args.recv_len = -1;
+ } else {
+ assert(err_is_ok(err));
+ }
+ } else {
+ err = event_dispatch(&ws);
+ assert(err_is_ok(err));
+ }
+
+/* #ifdef DEBUG_LATENCIES */
+/* if(posix_recv_transactions < POSIX_TRANSA) { */
+/* protocol_binary_request_no_extras *mypayload = buf + UDP_HEADLEN; */
+/* posix_recv_time[posix_recv_transactions] = get_time() - mypayload->message.header.request.opaque; */
+/* posix_recv_transactions++; */
+/* } */
+/* #endif */
+
+ // Packet is now in buffer
+ return args.recv_len;
+}
+
+int recvfrom_arranet(int sockfd, void **buf, struct packet **p,
+ struct sockaddr *src_addr, socklen_t *addrlen)
+{
+ assert(arranet_udp_accepted);
+ struct fdtab_entry *e = fdtab_get(sockfd);
+ struct socket *sock = &sockets[e->fd];
+ struct recv_udp_args args = {
+ .buf = buf,
+ .len = 0,
+ .src_addr = src_addr,
+ .addrlen = addrlen,
+ .inpkt = p,
+ .recv_len = 0,
+ };
+ struct waitset ws;
+ waitset_init(&ws);
+
+ errval_t err = waitset_chan_register_polled(&ws, &recv_chanstate,
+ MKCLOSURE(sock_recved_udp_packet, &args));
+ assert(err_is_ok(err));
+
+ /* if socket is ready, trigger event right away */
+ if (lwip_sock_ready_read(e->fd)) {
+ err = waitset_chan_trigger(&recv_chanstate);
+ assert(err_is_ok(err));
+ }
+
+ if(sock->nonblocking) {
+ err = event_dispatch_non_block(&ws);
+ if(err_no(err) == LIB_ERR_NO_EVENT) {
+ err = waitset_chan_deregister(&recv_chanstate);
+ assert(err_is_ok(err));
+ errno = EAGAIN;
+ args.recv_len = -1;
+ } else {
+ assert(err_is_ok(err));
+ }
+ } else {
+ err = event_dispatch(&ws);
+ assert(err_is_ok(err));
+ }
+
+/* #ifdef DEBUG_LATENCIES */
+/* if(posix_recv_transactions < POSIX_TRANSA) { */
+/* protocol_binary_request_no_extras *mypayload = (*buf) + UDP_HEADLEN; */
+/* posix_recv_time[posix_recv_transactions] = get_time() - mypayload->message.header.request.opaque; */
+/* posix_recv_transactions++; */
+/* } */
+/* #endif */
+
+ // XXX: Assert dword alignment
+ assert(((long)*buf) % 8 == 0);
+
+ // Packet is now in buffer
+ return args.recv_len;
+}
+
+static struct pkt_udp_headers packet_udp_header;
+static struct pkt_tcp_headers packet_tcp_header;
+
+static struct peer *peers_get_from_ip(uint32_t ip)
+{
+ for(int i = 0; i < MAX_PEERS; i++) {
+ if(ip == peers[i].ip) {
+ return &peers[i];
+ }
+ }
+
+ /* printf("NOT FOUND: %x\n", ip); */
+
+ return NULL;
+}
+
+static struct peer *peers_get_next_free(void)
+{
+ if(peers_alloc < MAX_PEERS) {
+ return &peers[peers_alloc++];
+ } else {
+ return NULL;
+ }
+}
+
+#define MAX_SENDMSG 16
+
+int sendmsg_arranet(int sockfd, const struct msghdr *msg)
+{
+ assert(arranet_udp_accepted);
+ struct fdtab_entry *e = fdtab_get(sockfd);
+ struct socket *sock = &sockets[e->fd];
+ ssize_t short_size = 0;
+ struct packet packets[MAX_SENDMSG];
+ struct packet hdrpkt;
+ struct packet *oldp = NULL;
+
+#ifdef DEBUG_LATENCIES
+ if(posix_send_transactions < POSIX_TRANSA) {
+ if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) {
+ protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base;
+ posix_send_time[posix_send_transactions] = get_time() - mypayload->message.header.response.opaque;
+ posix_send_transactions++;
+ } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) {
+ protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base;
+ posix_send_time[posix_send_transactions] = get_time() - mypayload->message.header.request.opaque;
+ posix_send_transactions++;
+ }
+ }
+#endif
+
+ assert(msg->msg_iovlen < MAX_SENDMSG);
+
+ for(int i = 0; i < msg->msg_iovlen; i++) {
+ struct packet *newp = &packets[i];
+
+ newp->payload = (uint8_t *)msg->msg_iov[i].iov_base;
+ newp->len = msg->msg_iov[i].iov_len;
+ newp->next = NULL;
+ newp->flags = 0;
+ if(oldp != NULL) {
+ oldp->next = newp;
+ }
+ short_size += msg->msg_iov[i].iov_len;
+ oldp = newp;
+ }
+
+ // Slap UDP/IP/Ethernet headers in front
+ struct pkt_udp_headers myhdr = packet_udp_header;
+ hdrpkt.payload = (uint8_t *)&myhdr;
+ struct pkt_udp_headers *p = (struct pkt_udp_headers *)hdrpkt.payload;
+ hdrpkt.len = sizeof(struct pkt_udp_headers);
+ hdrpkt.next = packets;
+
+ // Fine-tune headers
+ assert(msg->msg_name != NULL);
+ struct sockaddr_in *saddr = msg->msg_name;
+ assert(saddr->sin_family == AF_INET);
+ p->ip.dest.addr = saddr->sin_addr.s_addr;
+ p->udp.dest = saddr->sin_port;
+ struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+ p->eth.dest = peer->mac;
+ assert(sock->bound_addr.sin_port != 0);
+ p->udp.src = sock->bound_addr.sin_port;
+ p->udp.len = htons(short_size + sizeof(struct udp_hdr));
+ p->ip._len = htons(short_size + sizeof(struct udp_hdr) + IP_HLEN);
+#ifdef CONFIG_QEMU_NETWORK
+ p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+ hdrpkt.flags = 0;
+#else
+ // Hardware IP header checksumming on
+ p->ip._chksum = 0;
+ hdrpkt.flags = NETIF_TXFLAG_IPCHECKSUM;
+#endif
+
+ packet_output(&hdrpkt);
+
+ return short_size;
+}
+
+static struct packet *get_tx_packet(void)
+{
+ struct packet *p = &tx_packets[tx_idx];
+
+ // Busy-wait until packet not in flight
+ while(p->len != 0) {
+#ifdef DEBUG_LATENCIES
+ output_pipeline_stalled++;
+#endif
+ /* printf("Pipeline stalled! tx_packets_available = %zd\n", tx_packets_available); */
+ handle_free_tx_slot_fn_ptr();
+ /* if(!handle_free_tx_slot_fn_ptr()) { */
+ /* printf("No packets could be freed!\n"); */
+ /* } */
+ }
+
+ /* tx_packets_available--; */
+
+ tx_idx = (tx_idx + 1) % MAX_PACKETS;
+ return p;
+}
+
+int lwip_shutdown(int s, int how)
+{
+ assert(arranet_tcp_accepted);
+ struct socket *sock = &sockets[s];
+ assert(sock->nonblocking);
+
+ /* printf("lwip_shutdown(%d)\n", s); */
+
+ if(how == SHUT_RD || sock->shutdown) {
+ return 0;
+ }
+
+ sock->shutdown = true;
+
+#ifdef SENDMSG_WITH_COPY
+ // Get new TX packet and send FIN-ACK
+ struct packet *newp = get_tx_packet();
+ newp->len = sizeof(struct pkt_tcp_headers);
+ newp->next = NULL;
+
+ // Slap TCP/IP/Ethernet headers in front
+ memcpy(newp->payload, &packet_tcp_header, sizeof(struct pkt_tcp_headers));
+
+ // Fine-tune headers
+ struct pkt_tcp_headers *p = (struct pkt_tcp_headers *)newp->payload;
+ p->ip.dest.addr = sock->peer_addr.sin_addr.s_addr;
+ p->tcp.dest = sock->peer_addr.sin_port;
+ struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+ p->eth.dest = peer->mac;
+ assert(sock->bound_addr.sin_port != 0);
+ p->tcp.src = sock->bound_addr.sin_port;
+ p->ip._len = htons(sizeof(struct tcp_hdr) + IP_HLEN);
+ p->tcp.seqno = htonl(sock->my_seq++);
+ p->tcp.ackno = htonl(sock->next_ack);
+ /* printf("lwip_shutdown: Sending %p, seq %x, ack %x\n", sock, sock->my_seq - 1, sock->next_ack); */
+ TCPH_FLAGS_SET(&p->tcp, TCP_FIN | TCP_ACK); // Set FIN-ACK
+ TCPH_HDRLEN_SET(&p->tcp, 5); // 20 / 4
+ p->tcp.wnd = htons(11680);
+#ifdef CONFIG_QEMU_NETWORK
+ p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+ p->tcp.chksum = 0;
+ newp->payload = (uint8_t *)&p->tcp;
+ newp->len -= (uint8_t *)&p->tcp - (uint8_t *)p;
+ p->tcp.chksum = inet_chksum_pseudo(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+ IP_PROTO_TCP, TCP_HLEN);
+ newp->payload = (uint8_t *)p;
+ newp->len = sizeof(struct pkt_tcp_headers);
+ newp->flags = 0;
+#else
+ // Hardware IP/TCP header checksumming on
+ p->ip._chksum = 0;
+ p->tcp.chksum =
+ (~inet_chksum_pseudo_partial(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+ IP_PROTO_TCP, TCP_HLEN, 0)) & 0xffff;
+ newp->flags = (NETIF_TXFLAG_IPCHECKSUM | NETIF_TXFLAG_TCPCHECKSUM) |
+ (TCPH_HDRLEN(&p->tcp) << NETIF_TXFLAG_TCPHDRLEN_SHIFT);
+#endif
+
+ packet_output(newp);
+
+ return 0;
+#else
+ assert(!"NYI");
+#endif
+}
+
+int lwip_close(int s)
+{
+ assert(arranet_tcp_accepted);
+ struct socket *sock = &sockets[s];
+
+ lwip_shutdown(s, SHUT_RDWR);
+
+ // Might need to return port if it was bound
+ if(sock->bound_addr.sin_port != 0 && htons(sock->bound_addr.sin_port) != 8080) {
+ tcp_free_port(sock->bound_addr.sin_port);
+ }
+
+ // Remove from active connections
+ if(sock->prev != NULL) {
+ sock->prev->next = sock->next;
+ }
+ if(sock->next != NULL) {
+ sock->next->prev = sock->prev;
+ }
+ if(connections == sock) {
+ connections = sock->next;
+ }
+ sock->next = sock->prev = NULL;
+
+ free_socket(sock);
+ return 0;
+}
+
+int lwip_send(int s, const void *data, size_t size, int flags)
+{
+ assert(arranet_tcp_accepted);
+ struct socket *sock = &sockets[s];
+ assert(sock->nonblocking);
+ assert(size + sizeof(struct pkt_tcp_headers) <= 1500);
+
+ /* printf("lwip_send(%d, , %zu)\n", s, size); */
+
+#ifdef SENDMSG_WITH_COPY
+ // Get new TX packet and copy data into it
+ struct packet *newp = get_tx_packet();
+ newp->len = sizeof(struct pkt_tcp_headers) + size;
+ newp->next = NULL;
+ uint8_t *buf = newp->payload + sizeof(struct pkt_tcp_headers);
+ memcpy(buf, data, size);
+
+ // Slap TCP/IP/Ethernet headers in front
+ memcpy(newp->payload, &packet_tcp_header, sizeof(struct pkt_tcp_headers));
+
+ // Fine-tune headers
+ struct pkt_tcp_headers *p = (struct pkt_tcp_headers *)newp->payload;
+ p->ip.dest.addr = sock->peer_addr.sin_addr.s_addr;
+ p->tcp.dest = sock->peer_addr.sin_port;
+ struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+ assert(peer != NULL);
+ p->eth.dest = peer->mac;
+ assert(sock->bound_addr.sin_port != 0);
+ p->tcp.src = sock->bound_addr.sin_port;
+ p->ip._len = htons(sizeof(struct tcp_hdr) + IP_HLEN + size);
+ p->tcp.seqno = htonl(sock->my_seq);
+ sock->my_seq += size;
+ /* printf("lwip_send: Assigning %p, seq %x\n", sock, sock->my_seq); */
+ p->tcp.ackno = htonl(sock->next_ack);
+ /* printf("lwip_send: Sending %p, %x\n", sock, sock->next_ack); */
+ TCPH_FLAGS_SET(&p->tcp, TCP_ACK | TCP_PSH);
+ TCPH_HDRLEN_SET(&p->tcp, 5); // 20 / 4
+ p->tcp.wnd = htons(11680);
+#ifdef CONFIG_QEMU_NETWORK
+ p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+ p->tcp.chksum = 0;
+ newp->payload = (uint8_t *)&p->tcp;
+ newp->len -= (uint8_t *)&p->tcp - (uint8_t *)p;
+ p->tcp.chksum = inet_chksum_pseudo(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+ IP_PROTO_TCP, TCP_HLEN + size);
+ newp->payload = (uint8_t *)p;
+ newp->len = sizeof(struct pkt_tcp_headers) + size;
+ newp->flags = 0;
+#else
+ // Hardware IP/TCP header checksumming on
+ p->ip._chksum = 0;
+ p->tcp.chksum =
+ (~inet_chksum_pseudo_partial(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+ IP_PROTO_TCP, TCP_HLEN + size, 0)) & 0xffff;
+ newp->flags = (NETIF_TXFLAG_IPCHECKSUM | NETIF_TXFLAG_TCPCHECKSUM) |
+ (TCPH_HDRLEN(&p->tcp) << NETIF_TXFLAG_TCPHDRLEN_SHIFT);
+#endif
+
+ packet_output(newp);
+
+ return size;
+#else
+ assert(!"NYI");
+#endif
+}
+
+int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ /* printf("lwip_connect(%d)\n", s); */
+ assert(arranet_tcp_accepted);
+ struct socket *sock = &sockets[s];
+ assert(sock->nonblocking);
+ assert(namelen == sizeof(struct sockaddr_in));
+ struct sockaddr_in *sa = (struct sockaddr_in *)name;
+ assert(sa->sin_family == AF_INET);
+
+ // Store peer address on socket
+ sock->peer_addr = *sa;
+
+#ifdef SENDMSG_WITH_COPY
+ // Get new TX packet and send SYN
+ struct packet *newp = get_tx_packet();
+ newp->len = sizeof(struct pkt_tcp_headers) + 6;
+ newp->next = NULL;
+
+ // Slap TCP/IP/Ethernet headers in front
+ memcpy(newp->payload, &packet_tcp_header, sizeof(struct pkt_tcp_headers));
+
+ // Fine-tune headers
+ struct pkt_tcp_headers *p = (struct pkt_tcp_headers *)newp->payload;
+ uint32_t *payload = (void *)p + sizeof(struct pkt_tcp_headers);
+ memset(payload, 0, 6);
+ p->ip.dest.addr = sa->sin_addr.s_addr;
+ p->tcp.dest = sa->sin_port;
+ struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+ assert(peer != NULL);
+ p->eth.dest = peer->mac;
+ assert(sock->bound_addr.sin_port == 0);
+ sock->bound_addr.sin_port = tcp_new_port();
+ p->tcp.src = sock->bound_addr.sin_port;
+ p->ip._len = htons(sizeof(struct tcp_hdr) + IP_HLEN + 4);
+ p->tcp.seqno = htonl(++sock->my_seq); sock->my_seq++;
+ /* printf("lwip_connect: Assigning %p seq %x\n", sock, sock->my_seq); */
+ p->tcp.ackno = 0;
+ TCPH_FLAGS_SET(&p->tcp, TCP_SYN);
+ TCPH_HDRLEN_SET(&p->tcp, 6); // 24 / 4
+ p->tcp.wnd = htons(11680);
+ *payload = TCP_BUILD_MSS_OPTION(1460);
+#ifdef CONFIG_QEMU_NETWORK
+ p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+ p->tcp.chksum = 0;
+ newp->payload = (uint8_t *)&p->tcp;
+ newp->len -= (uint8_t *)&p->tcp - (uint8_t *)p;
+ p->tcp.chksum = inet_chksum_pseudo(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+ IP_PROTO_TCP, TCP_HLEN + 4);
+ newp->payload = (uint8_t *)p;
+ newp->len = sizeof(struct pkt_tcp_headers) + 6;
+ newp->flags = 0;
+#else
+ // Hardware IP/TCP header checksumming on
+ p->ip._chksum = 0;
+ p->tcp.chksum = 0;
+ p->tcp.chksum =
+ (~inet_chksum_pseudo_partial(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+ IP_PROTO_TCP, TCP_HLEN + 4, 0)) & 0xffff;
+ newp->flags = (NETIF_TXFLAG_IPCHECKSUM | NETIF_TXFLAG_TCPCHECKSUM) |
+ (TCPH_HDRLEN(&p->tcp) << NETIF_TXFLAG_TCPHDRLEN_SHIFT);
+#endif
+
+ packet_output(newp);
+
+ assert(sock->prev == NULL && sock->next == NULL);
+ sock->next = connections;
+ if(connections != NULL) {
+ assert(connections->prev == NULL);
+ connections->prev = sock;
+ }
+ sock->prev = NULL;
+ connections = sock;
+
+ errno = EINPROGRESS;
+ return -1;
+#else
+ assert(!"NYI");
+#endif
+}
+
+#ifdef SENDMSG_WITH_COPY
+
+int lwip_sendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+ assert(arranet_udp_accepted);
+ struct socket *sock = &sockets[sockfd];
+
+#ifdef DEBUG_LATENCIES
+ if(posix_send_transactions < POSIX_TRANSA) {
+ if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) {
+ protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base;
+ posix_send_time[posix_send_transactions] = get_time() - mypayload->message.header.response.opaque;
+ posix_send_transactions++;
+ } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) {
+ protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN;
+ posix_send_time[posix_send_transactions] = get_time() - mypayload->message.header.request.opaque;
+ posix_send_transactions++;
+ }
+ }
+#endif
+
+ assert(msg->msg_iovlen < MAX_SENDMSG);
+
+ // Determine length of sendmsg vector
+ ssize_t short_size = 0;
+ for(int i = 0; i < msg->msg_iovlen; i++) {
+ short_size += msg->msg_iov[i].iov_len;
+ }
+ assert(short_size <= PACKET_SIZE);
+
+/* #ifdef DEBUG_LATENCIES */
+/* if(memcache_transactions[0] < POSIX_TRANSA) { */
+/* if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/* protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/* memcache_times[0][memcache_transactions[0]] = get_time() - mypayload->message.header.response.opaque; */
+/* memcache_transactions[0]++; */
+/* } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/* protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/* memcache_times[0][memcache_transactions[0]] = get_time() - mypayload->message.header.request.opaque; */
+/* memcache_transactions[0]++; */
+/* } */
+/* } */
+/* #endif */
+
+ // Get new TX packet and copy data into it
+ struct packet *newp = get_tx_packet();
+ uint8_t *buf = newp->payload;
+ size_t pos = sizeof(struct pkt_udp_headers);
+
+/* #ifdef DEBUG_LATENCIES */
+/* if(memcache_transactions[1] < POSIX_TRANSA) { */
+/* if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/* protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/* memcache_times[1][memcache_transactions[1]] = get_time() - mypayload->message.header.response.opaque; */
+/* memcache_transactions[1]++; */
+/* } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/* protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/* memcache_times[1][memcache_transactions[1]] = get_time() - mypayload->message.header.request.opaque; */
+/* memcache_transactions[1]++; */
+/* } */
+/* } */
+
+/* uint64_t last = rdpmc(0); */
+/* #endif */
+
+ // assert(msg->msg_iovlen == 1);
+ for(int i = 0; i < msg->msg_iovlen; i++) {
+ /* assert((uintptr_t)(&buf[pos]) % 8 == 0); */
+ // assert((uintptr_t)msg->msg_iov[i].iov_base % 8 == 0);
+ memcpy(&buf[pos], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
+ pos += msg->msg_iov[i].iov_len;
+ }
+
+#ifdef DEBUG_LATENCIES
+ /* uint64_t now = rdpmc(0); */
+
+ /* if(memcache_transactions[19] < POSIX_TRANSA) { // ZZZ 19 */
+ /* memcache_times[19][memcache_transactions[19]] = now - last; */
+ /* memcache_transactions[19]++; */
+ /* } */
+
+ if(memcache_transactions[2] < POSIX_TRANSA) {
+ if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) {
+ protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base;
+ memcache_times[2][memcache_transactions[2]] = get_time() - mypayload->message.header.response.opaque;
+ memcache_transactions[2]++;
+ } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) {
+ protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN;
+ memcache_times[2][memcache_transactions[2]] = get_time() - mypayload->message.header.request.opaque;
+ memcache_transactions[2]++;
+ }
+ }
+#endif
+
+ newp->len = short_size + sizeof(struct pkt_udp_headers);
+ newp->next = NULL;
+
+ // Slap UDP/IP/Ethernet headers in front
+ memcpy(buf, &packet_udp_header, sizeof(struct pkt_udp_headers));
+
+/* #ifdef DEBUG_LATENCIES */
+/* if(memcache_transactions[3] < POSIX_TRANSA) { */
+/* if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/* protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/* memcache_times[3][memcache_transactions[3]] = get_time() - mypayload->message.header.response.opaque; */
+/* memcache_transactions[3]++; */
+/* } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/* protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/* memcache_times[3][memcache_transactions[3]] = get_time() - mypayload->message.header.request.opaque; */
+/* memcache_transactions[3]++; */
+/* } */
+/* } */
+/* #endif */
+
+ // Fine-tune headers
+ struct pkt_udp_headers *p = (struct pkt_udp_headers *)buf;
+ assert(msg->msg_name != NULL);
+ struct sockaddr_in *saddr = msg->msg_name;
+ assert(saddr->sin_family == AF_INET);
+ p->ip.dest.addr = saddr->sin_addr.s_addr;
+ p->udp.dest = saddr->sin_port;
+ struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+ p->eth.dest = peer->mac;
+ assert(sock->bound_addr.sin_port != 0);
+ p->udp.src = sock->bound_addr.sin_port;
+ p->udp.len = htons(short_size + sizeof(struct udp_hdr));
+ p->ip._len = htons(short_size + sizeof(struct udp_hdr) + IP_HLEN);
+#ifdef CONFIG_QEMU_NETWORK
+ p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+ newp->flags = 0;
+#else
+ // Hardware IP header checksumming on
+ p->ip._chksum = 0;
+ newp->flags = NETIF_TXFLAG_IPCHECKSUM;
+#endif
+
+/* #ifdef DEBUG_LATENCIES */
+/* if(memcache_transactions[4] < POSIX_TRANSA) { */
+/* if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/* protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/* memcache_times[4][memcache_transactions[4]] = get_time() - mypayload->message.header.response.opaque; */
+/* memcache_transactions[4]++; */
+/* } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/* protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/* memcache_times[4][memcache_transactions[4]] = get_time() - mypayload->message.header.request.opaque; */
+/* memcache_transactions[4]++; */
+/* } */
+/* } */
+/* #endif */
+
+ packet_output(newp);
+
+/* #ifdef DEBUG_LATENCIES */
+/* if(memcache_transactions[5] < POSIX_TRANSA) { */
+/* if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/* protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/* memcache_times[5][memcache_transactions[5]] = get_time() - mypayload->message.header.response.opaque; */
+/* memcache_transactions[5]++; */
+/* } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/* protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/* memcache_times[5][memcache_transactions[5]] = get_time() - mypayload->message.header.request.opaque; */
+/* memcache_transactions[5]++; */
+/* } */
+/* } */
+/* #endif */
+
+ return short_size;
+}
+
+#else
+
+int lwip_sendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+ struct socket *sock = &sockets[sockfd];
+ ssize_t short_size = 0;
+ struct packet packets[MAX_SENDMSG];
+ struct packet *oldp = NULL;
+
+ assert(msg->msg_iovlen < MAX_SENDMSG);
+
+ for(int i = 0; i < msg->msg_iovlen; i++) {
+ struct packet *newp = &packets[i];
+
+ newp->payload = (uint8_t *)msg->msg_iov[i].iov_base;
+ newp->len = msg->msg_iov[i].iov_len;
+ newp->next = NULL;
+ newp->flags = 0;
+ newp->opaque = msg->msg_iov[i].iov_opaque;
+ if(oldp != NULL) {
+ oldp->next = newp;
+ }
+ short_size += msg->msg_iov[i].iov_len;
+ oldp = newp;
+ }
+
+ // Slap UDP/IP/Ethernet headers in front
+ struct packet *hdrpkt = get_tx_packet();
+ memcpy(hdrpkt->payload, &packet_udp_header, sizeof(struct pkt_udp_headers));
+ struct pkt_udp_headers *p = (struct pkt_udp_headers *)hdrpkt->payload;
+ hdrpkt->len = sizeof(struct pkt_udp_headers);
+ hdrpkt->next = packets;
+ hdrpkt->opaque = hdrpkt;
+
+ // Fine-tune headers
+ assert(msg->msg_name != NULL);
+ struct sockaddr_in *saddr = msg->msg_name;
+ assert(saddr->sin_family == AF_INET);
+ p->ip.dest.addr = saddr->sin_addr.s_addr;
+ p->udp.dest = saddr->sin_port;
+ struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+ p->eth.dest = peer->mac;
+ assert(sock->bound_addr.sin_port != 0);
+ p->udp.src = sock->bound_addr.sin_port;
+ p->udp.len = htons(short_size + sizeof(struct udp_hdr));
+ p->ip._len = htons(short_size + sizeof(struct udp_hdr) + IP_HLEN);
+#ifdef CONFIG_QEMU_NETWORK
+ p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+ hdrpkt->flags = 0;
+#else
+ // Hardware IP header checksumming on
+ p->ip._chksum = 0;
+ hdrpkt->flags = NETIF_TXFLAG_IPCHECKSUM;
+#endif
+
+ packet_output(hdrpkt);
+
+ // If we sent the data directly, we need to wait here until everything is out.
+ // Else, data might be overwritten by application before card can send it.
+ /* while(!e1000n_queue_empty()) thread_yield(); */
+
+ return short_size;
+}
+
+#endif
+
+int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+ assert(arranet_tcp_accepted);
+ struct socket *sock = &sockets[s];
+ assert(sock->passive);
+ struct socket *newsock = alloc_socket();
+ newsock->nonblocking = sock->nonblocking;
+ newsock->bound_addr = sock->bound_addr;
+ socklen_t adlen = sizeof(struct sockaddr_in);
+ struct recv_tcp_args args = {
+ .buf = NULL,
+ .len = 0,
+ .src_addr = (struct sockaddr *)&newsock->peer_addr,
+ .addrlen = &adlen,
+ .syn = false,
+ .sock = newsock,
+ };
+ struct waitset ws;
+ waitset_init(&ws);
+
+ errval_t err = waitset_chan_register_polled(&ws, &recv_chanstate,
+ MKCLOSURE(sock_recved_tcp_packet, &args));
+ assert(err_is_ok(err));
+
+ /* if socket is ready, trigger event right away */
+ if (lwip_sock_ready_read(s)) {
+ err = waitset_chan_trigger(&recv_chanstate);
+ assert(err_is_ok(err));
+ }
+
+ if(sock->nonblocking) {
+ err = event_dispatch_non_block(&ws);
+ if(err_no(err) == LIB_ERR_NO_EVENT) { // Deregister if it didn't fire
+ err = waitset_chan_deregister(&recv_chanstate);
+ assert(err_is_ok(err));
+ }
+
+ if(err_no(err) == LIB_ERR_NO_EVENT || !args.syn) {
+ free_socket(newsock);
+ errno = EAGAIN;
+ return -1;
+ } else {
+ assert(err_is_ok(err));
+ }
+
+ if(!args.syn) {
+ free_socket(newsock);
+ errno = EAGAIN;
+ return -1;
+ }
+ } else {
+ err = event_dispatch(&ws);
+ assert(err_is_ok(err));
+
+ if(!args.syn) {
+ assert(!"Will block forever");
+ }
+ }
+
+ assert(adlen == sizeof(struct sockaddr_in));
+ assert(*addrlen >= sizeof(struct sockaddr_in));
+ // Set caller's addr buffers
+ if(addr != NULL) {
+ memcpy(addr, &newsock->peer_addr, sizeof(struct sockaddr_in));
+ *addrlen = adlen;
+ }
+
+ /* newsock->my_seq = 0; */
+ newsock->peer_seq = htonl(args.in_seqno);
+ /* printf("lwip_accept: Assigning %p seq %x\n", newsock, newsock->my_seq); */
+
+#ifdef SENDMSG_WITH_COPY
+ // Get new TX packet and send SYN-ACK
+ struct packet *newp = get_tx_packet();
+ newp->len = sizeof(struct pkt_tcp_headers) + 4;
+ newp->next = NULL;
+
+ // Slap TCP/IP/Ethernet headers in front
+ memcpy(newp->payload, &packet_tcp_header, sizeof(struct pkt_tcp_headers));
+
+ // Fine-tune headers
+ struct pkt_tcp_headers *p = (struct pkt_tcp_headers *)newp->payload;
+ uint32_t *payload = (void *)p + sizeof(struct pkt_tcp_headers);
+ memset(payload, 0, 4);
+ p->ip.dest.addr = newsock->peer_addr.sin_addr.s_addr;
+ p->tcp.dest = newsock->peer_addr.sin_port;
+ struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+ p->eth.dest = peer->mac;
+ assert(sock->bound_addr.sin_port != 0);
+ p->tcp.src = sock->bound_addr.sin_port;
+ p->ip._len = htons(sizeof(struct tcp_hdr) + IP_HLEN + 4);
+ p->tcp.seqno = htonl(++newsock->my_seq); newsock->my_seq++;
+ /* printf("lwip_accept: Assigning %p seq %x\n", newsock, newsock->my_seq); */
+ newsock->next_ack = newsock->peer_seq + 1;
+ /* printf("lwip_accept: Assigning %p, %x\n", newsock, newsock->next_ack); */
+ p->tcp.ackno = htonl(newsock->next_ack);
+ /* printf("lwip_accept: Sending %p, %x\n", newsock, newsock->next_ack); */
+ TCPH_FLAGS_SET(&p->tcp, TCP_SYN | TCP_ACK); // Set SYN-ACK
+ TCPH_HDRLEN_SET(&p->tcp, 6); // 24 / 4
+ p->tcp.wnd = htons(11680);
+ *payload = TCP_BUILD_MSS_OPTION(1460);
+#ifdef CONFIG_QEMU_NETWORK
+ p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+ p->tcp.chksum = 0;
+ newp->payload = (uint8_t *)&p->tcp;
+ newp->len -= (uint8_t *)&p->tcp - (uint8_t *)p;
+ p->tcp.chksum = inet_chksum_pseudo(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+ IP_PROTO_TCP, TCP_HLEN + 4);
+ newp->payload = (uint8_t *)p;
+ newp->len = sizeof(struct pkt_tcp_headers) + 4;
+ newp->flags = 0;
+#else
+ // Hardware IP/TCP header checksumming on
+ p->ip._chksum = 0;
+ p->tcp.chksum =
+ (~inet_chksum_pseudo_partial(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+ IP_PROTO_TCP, TCP_HLEN + 4, 0)) & 0xffff;
+ newp->flags = (NETIF_TXFLAG_IPCHECKSUM | NETIF_TXFLAG_TCPCHECKSUM) |
+ (6 << NETIF_TXFLAG_TCPHDRLEN_SHIFT);
+#endif
+
+ packet_output(newp);
+#else
+ assert(!"NYI");
+#endif
+
+ /* printf("Returned %d\n", newsock->fd); */
+ newsock->connected = true;
+ assert(newsock->prev == NULL && newsock->next == NULL);
+ newsock->next = connections;
+ if(connections != NULL) {
+ assert(connections->prev == NULL);
+ connections->prev = newsock;
+ }
+ newsock->prev = NULL;
+ connections = newsock;
+
+ /* printf("lwip_accept(%d) = %d\n", s, newsock->fd); */
+ return newsock->fd;
+}
+
+void process_received_packet(struct driver_rx_buffer *buffer, size_t count,
+ uint64_t flags)
+{
+ struct packet *p = buffer->opaque;
+ assert(p != NULL);
+ assert(count == 1);
+ p->len = buffer->len;
+
+ /* printf("Got %p from driver\n", p); */
+
+ assert(p >= rx_packets && p < &rx_packets[MAX_PACKETS]);
+
+#ifdef DEBUG_LATENCIES
+ rx_packets_available--;
+ if(rx_packets_available < 10) {
+ printf("Too many RX packets in flight!\n");
+ }
+#endif
+
+ // Drop packets with invalid checksums
+ if(flags & NETIF_RXFLAG_IPCHECKSUM) {
+ if(!(flags & NETIF_RXFLAG_IPCHECKSUM_GOOD)) {
+ goto out;
+ }
+ }
+
+ if(flags & NETIF_RXFLAG_L4CHECKSUM) {
+ if(!(flags & NETIF_RXFLAG_L4CHECKSUM_GOOD)) {
+ goto out;
+ }
+ }
+
+ struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
+ switch (htons(ethhdr->type)) {
+ case ETHTYPE_ARP:
+ {
+ struct etharp_hdr *arphdr = (struct etharp_hdr *)(p->payload + SIZEOF_ETH_HDR);
+ uint32_t dipaddr = (arphdr->dipaddr.addrw[1] << 16) | arphdr->dipaddr.addrw[0];
+
+ /* printf("%d: ARP request, dip = %x\n", disp_get_core_id(), dipaddr); */
+
+ if(htons(arphdr->opcode) == ARP_REQUEST &&
+ dipaddr == arranet_myip) {
+ // Send reply
+ struct packet outp;
+ uint8_t payload[PACKET_SIZE];
+ struct eth_hdr *myeth = (struct eth_hdr *)payload;
+ struct etharp_hdr *myarp = (struct etharp_hdr *)(payload + SIZEOF_ETH_HDR);
+
+ /* printf("%d: ARP request for us!\n", disp_get_core_id()); */
+
+ // ETH header
+ memcpy(&myeth->dest, &arphdr->shwaddr, ETHARP_HWADDR_LEN);
+ memcpy(&myeth->src, arranet_mymac, ETHARP_HWADDR_LEN);
+ myeth->type = htons(ETHTYPE_ARP);
+
+ // ARP header
+ myarp->hwtype = htons(1);
+ myarp->proto = htons(ETHTYPE_IP);
+ myarp->hwlen = 6;
+ myarp->protolen = 4;
+ myarp->opcode = htons(ARP_REPLY);
+ memcpy(&myarp->shwaddr, arranet_mymac, ETHARP_HWADDR_LEN);
+ memcpy(&myarp->sipaddr, &arphdr->dipaddr, sizeof(myarp->sipaddr));
+ memcpy(&myarp->dhwaddr, &arphdr->shwaddr, ETHARP_HWADDR_LEN);
+ memcpy(&myarp->dipaddr, &arphdr->sipaddr, sizeof(myarp->dipaddr));
+
+ outp.payload = payload;
+ outp.len = p->len;
+ outp.next = NULL;
+ outp.flags = 0;
+ outp.opaque = NULL;
+ packet_output(&outp);
+ while(!e1000n_queue_empty()) thread_yield();
+ }
+ }
+ break;
+
+ case ETHTYPE_IP:
+ {
+ struct ip_hdr *iphdr = (struct ip_hdr *)(p->payload + SIZEOF_ETH_HDR);
+
+ /* printf("%d: Is an IP packet, type %x\n", disp_get_core_id(), IPH_PROTO(iphdr)); */
+
+#ifdef DEBUG_LATENCIES
+ if(IPH_PROTO(iphdr) == IP_PROTO_ICMP) {
+ static uint64_t cache_misses = 0;
+ uint64_t new_cache_misses = rdpmc(0);
+ printf("Cache misses = %" PRIu64 "\n", new_cache_misses - cache_misses);
+ cache_misses = new_cache_misses;
+
+ printf("hash_option1 = %zd, hash_option2 = %zd, hash_option3 = %zd\n",
+ hash_option1, hash_option2, hash_option3);
+ printf("hash_calls = %zd, hash_length = %zd\n",
+ hash_calls, hash_length);
+
+ printf("output pipeline stalled = %zd\n", output_pipeline_stalled);
+ output_pipeline_stalled = 0;
+
+ printf("memcache packets received = %zd\n", memcache_packets_received);
+ memcache_packets_received = 0;
+ for(int i = 0; i < 65536; i++) {
+ if(port_cnt[i] != 0) {
+ printf("port %d = %zu\n", i, port_cnt[i]);
+ port_cnt[i] = 0;
+ }
+ }
+
+ printf("recv_transa = %zu, send_transa = %zu\n",
+ posix_recv_transactions, posix_send_transactions);
+ printf("posix_recv_transactions:\n");
+ for(int i = 0; i < posix_recv_transactions; i++) {
+ printf("%u us\n", posix_recv_time[i]);
+ }
+ printf("posix_send_transactions:\n");
+ for(int i = 0; i < posix_send_transactions; i++) {
+ printf("%u us\n", posix_send_time[i]);
+ }
+ posix_recv_transactions = posix_send_transactions = 0;
+
+ printf("lwip_send_transa = %zu\n", lwip_send_transactions);
+ printf("lwip_send_transactions:\n");
+ for(int i = 0; i < lwip_send_transactions; i++) {
+ printf("%u us\n", lwip_send_time[i]);
+ }
+ lwip_send_transactions = 0;
+
+ for(int j = 0; j < 20; j++) {
+ printf("memcache_transa[%d] = %zu:\n", j, memcache_transactions[j]);
+ for(int i = 0; i < memcache_transactions[j]; i++) {
+ printf("%u us\n", memcache_times[j][i]);
+ }
+ memcache_transactions[j] = 0;
+ }
+ }
+#endif
+
+ // Has to be UDP or TCP
+ if(IPH_PROTO(iphdr) != IP_PROTO_UDP && IPH_PROTO(iphdr) != IP_PROTO_TCP) {
+ goto out;
+ }
+
+ // XXX: Filter for our IP
+ if(iphdr->dest.addr != arranet_myip) {
+ goto out;
+ }
+
+ if(IPH_PROTO(iphdr) == IP_PROTO_UDP) {
+ struct udp_hdr *udphdr = (struct udp_hdr *)(p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+ /* uint8_t *payload = p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr); */
+
+ // Are we accepting UDP packets?
+ if(!arranet_udp_accepted) {
+ goto out;
+ }
+
+ /* printf("Got UDP packet, dest IP %x, dest port %u\n", */
+ /* htonl(iphdr->dest.addr), htons(udphdr->dest)); */
+
+ // XXX: Filter for UDP ports 1234, 11211, 11212
+ // TODO: Done in hardware soon
+ if(htons(udphdr->dest) != 1234 &&
+ htons(udphdr->dest) != 11211 &&
+ htons(udphdr->dest) != 11212) {
+ goto out;
+ }
+
+#ifdef DEBUG_LATENCIES
+ {
+ memcache_packets_received++;
+ port_cnt[htons(udphdr->src)]++;
+ protocol_binary_request_no_extras *mypayload = (void *)p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr) + UDP_HEADLEN;
+ mypayload->message.header.request.opaque = get_time();
+ }
+#endif
+ }
+
+ if(IPH_PROTO(iphdr) == IP_PROTO_TCP) {
+ struct tcp_hdr *tcphdr = (struct tcp_hdr *)(p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+
+ // Are we accepting TCP packets?
+ if(!arranet_tcp_accepted) {
+ goto out;
+ }
+
+ /* printf("Got TCP packet, dest IP %x, src IP %x, dest port %u, src %u\n", */
+ /* htonl(iphdr->dest.addr), htonl(iphdr->src.addr), */
+ /* htons(tcphdr->dest), htons(tcphdr->src)); */
+
+ // XXX: Filter for TCP port 8080 and everything that we know
+ // TODO: Done in hardware soon
+ struct socket *sock = NULL;
+ for(sock = connections; sock != NULL; sock = sock->next) {
+ if(sock->bound_addr.sin_port == tcphdr->dest &&
+ sock->peer_addr.sin_port == tcphdr->src &&
+ sock->peer_addr.sin_addr.s_addr == iphdr->src.addr) {
+ break;
+ }
+ }
+
+ p->sock = sock;
+
+ // Handle SYN-ACKs for connections we created and